mirror of
https://github.com/fastapi/fastapi.git
synced 2026-05-25 00:37:44 -04:00
✅ Add missing tests for code examples (#14569)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Nils-Hero Lindemann <nilsherolindemann@proton.me>
This commit is contained in:
161
tests/test_tutorial/test_body/test_tutorial002.py
Normal file
161
tests/test_tutorial/test_body/test_tutorial002.py
Normal file
@@ -0,0 +1,161 @@
|
||||
import importlib
|
||||
from typing import Union
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.body.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
@pytest.mark.parametrize("price", ["50.5", 50.5])
|
||||
def test_post_with_tax(client: TestClient, price: Union[str, float]):
|
||||
response = client.post(
|
||||
"/items/",
|
||||
json={"name": "Foo", "price": price, "description": "Some Foo", "tax": 0.3},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"name": "Foo",
|
||||
"price": 50.5,
|
||||
"description": "Some Foo",
|
||||
"tax": 0.3,
|
||||
"price_with_tax": 50.8,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("price", ["50.5", 50.5])
|
||||
def test_post_without_tax(client: TestClient, price: Union[str, float]):
|
||||
response = client.post(
|
||||
"/items/", json={"name": "Foo", "price": price, "description": "Some Foo"}
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"name": "Foo",
|
||||
"price": 50.5,
|
||||
"description": "Some Foo",
|
||||
"tax": None,
|
||||
}
|
||||
|
||||
|
||||
def test_post_with_no_data(client: TestClient):
|
||||
response = client.post("/items/", json={})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "name"],
|
||||
"msg": "Field required",
|
||||
"input": {},
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "price"],
|
||||
"msg": "Field required",
|
||||
"input": {},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"post": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Create Item",
|
||||
"operationId": "create_item_items__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": ["name", "price"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
171
tests/test_tutorial/test_body/test_tutorial003.py
Normal file
171
tests/test_tutorial/test_body/test_tutorial003.py
Normal file
@@ -0,0 +1,171 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial003_py39"),
|
||||
pytest.param("tutorial003_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.body.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_put_all(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/123",
|
||||
json={"name": "Foo", "price": 50.1, "description": "Some Foo", "tax": 0.3},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"item_id": 123,
|
||||
"name": "Foo",
|
||||
"price": 50.1,
|
||||
"description": "Some Foo",
|
||||
"tax": 0.3,
|
||||
}
|
||||
|
||||
|
||||
def test_put_only_required(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/123",
|
||||
json={"name": "Foo", "price": 50.1},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"item_id": 123,
|
||||
"name": "Foo",
|
||||
"price": 50.1,
|
||||
"description": None,
|
||||
"tax": None,
|
||||
}
|
||||
|
||||
|
||||
def test_put_with_no_data(client: TestClient):
|
||||
response = client.put("/items/123", json={})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "name"],
|
||||
"msg": "Field required",
|
||||
"input": {},
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "price"],
|
||||
"msg": "Field required",
|
||||
"input": {},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"put": {
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "item_id",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "Item Id",
|
||||
"type": "integer",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Update Item",
|
||||
"operationId": "update_item_items__item_id__put",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": ["name", "price"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
182
tests/test_tutorial/test_body/test_tutorial004.py
Normal file
182
tests/test_tutorial/test_body/test_tutorial004.py
Normal file
@@ -0,0 +1,182 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial004_py39"),
|
||||
pytest.param("tutorial004_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.body.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_put_all(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/123",
|
||||
json={"name": "Foo", "price": 50.1, "description": "Some Foo", "tax": 0.3},
|
||||
params={"q": "somequery"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"item_id": 123,
|
||||
"name": "Foo",
|
||||
"price": 50.1,
|
||||
"description": "Some Foo",
|
||||
"tax": 0.3,
|
||||
"q": "somequery",
|
||||
}
|
||||
|
||||
|
||||
def test_put_only_required(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/123",
|
||||
json={"name": "Foo", "price": 50.1},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"item_id": 123,
|
||||
"name": "Foo",
|
||||
"price": 50.1,
|
||||
"description": None,
|
||||
"tax": None,
|
||||
}
|
||||
|
||||
|
||||
def test_put_with_no_data(client: TestClient):
|
||||
response = client.put("/items/123", json={})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "name"],
|
||||
"msg": "Field required",
|
||||
"input": {},
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "price"],
|
||||
"msg": "Field required",
|
||||
"input": {},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"put": {
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "item_id",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "Item Id",
|
||||
"type": "integer",
|
||||
},
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Update Item",
|
||||
"operationId": "update_item_items__item_id__put",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": ["name", "price"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,361 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.body_multiple_params.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_post_all(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"price": 50.5,
|
||||
"description": "Some Foo",
|
||||
"tax": 0.1,
|
||||
},
|
||||
"user": {"username": "johndoe", "full_name": "John Doe"},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"item_id": 5,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"price": 50.5,
|
||||
"description": "Some Foo",
|
||||
"tax": 0.1,
|
||||
},
|
||||
"user": {"username": "johndoe", "full_name": "John Doe"},
|
||||
}
|
||||
|
||||
|
||||
def test_post_required(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"item": {"name": "Foo", "price": 50.5},
|
||||
"user": {"username": "johndoe"},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"item_id": 5,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"price": 50.5,
|
||||
"description": None,
|
||||
"tax": None,
|
||||
},
|
||||
"user": {"username": "johndoe", "full_name": None},
|
||||
}
|
||||
|
||||
|
||||
def test_post_no_body(client: TestClient):
|
||||
response = client.put("/items/5", json=None)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": [
|
||||
"body",
|
||||
"item",
|
||||
],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"input": None,
|
||||
"loc": [
|
||||
"body",
|
||||
"user",
|
||||
],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_post_no_item(client: TestClient):
|
||||
response = client.put("/items/5", json={"user": {"username": "johndoe"}})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": [
|
||||
"body",
|
||||
"item",
|
||||
],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_post_no_user(client: TestClient):
|
||||
response = client.put("/items/5", json={"item": {"name": "Foo", "price": 50.5}})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": [
|
||||
"body",
|
||||
"user",
|
||||
],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_post_missing_required_field_in_item(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5", json={"item": {"name": "Foo"}, "user": {"username": "johndoe"}}
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": {"name": "Foo"},
|
||||
"loc": [
|
||||
"body",
|
||||
"item",
|
||||
"price",
|
||||
],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_post_missing_required_field_in_user(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={"item": {"name": "Foo", "price": 50.5}, "user": {"ful_name": "John Doe"}},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": {"ful_name": "John Doe"},
|
||||
"loc": [
|
||||
"body",
|
||||
"user",
|
||||
"username",
|
||||
],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_post_id_foo(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/foo",
|
||||
json={
|
||||
"item": {"name": "Foo", "price": 50.5},
|
||||
"user": {"username": "johndoe"},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["path", "item_id"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "foo",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0",
|
||||
},
|
||||
"openapi": "3.1.0",
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"put": {
|
||||
"operationId": "update_item_items__item_id__put",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "item_id",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "Item Id",
|
||||
"type": "integer",
|
||||
},
|
||||
},
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_update_item_items__item_id__put",
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
"summary": "Update Item",
|
||||
},
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_update_item_items__item_id__put": {
|
||||
"properties": {
|
||||
"item": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
},
|
||||
"user": {
|
||||
"$ref": "#/components/schemas/User",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"item",
|
||||
"user",
|
||||
],
|
||||
"title": "Body_update_item_items__item_id__put",
|
||||
"type": "object",
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"price",
|
||||
],
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
},
|
||||
"User": {
|
||||
"properties": {
|
||||
"username": {
|
||||
"title": "Username",
|
||||
"type": "string",
|
||||
},
|
||||
"full_name": {
|
||||
"title": "Full Name",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"username",
|
||||
],
|
||||
"title": "User",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial004_py39"),
|
||||
pytest.param("tutorial004_py310", marks=needs_py310),
|
||||
pytest.param("tutorial004_an_py39"),
|
||||
pytest.param("tutorial004_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.body_multiple_params.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_put_all(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"importance": 2,
|
||||
"item": {"name": "Foo", "price": 50.5},
|
||||
"user": {"username": "Dave"},
|
||||
},
|
||||
params={"q": "somequery"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"item_id": 5,
|
||||
"importance": 2,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"price": 50.5,
|
||||
"description": None,
|
||||
"tax": None,
|
||||
},
|
||||
"user": {"username": "Dave", "full_name": None},
|
||||
"q": "somequery",
|
||||
}
|
||||
|
||||
|
||||
def test_put_only_required(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"importance": 2,
|
||||
"item": {"name": "Foo", "price": 50.5},
|
||||
"user": {"username": "Dave"},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"item_id": 5,
|
||||
"importance": 2,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"price": 50.5,
|
||||
"description": None,
|
||||
"tax": None,
|
||||
},
|
||||
"user": {"username": "Dave", "full_name": None},
|
||||
}
|
||||
|
||||
|
||||
def test_put_missing_body(client: TestClient):
|
||||
response = client.put("/items/5")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": [
|
||||
"body",
|
||||
"item",
|
||||
],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"input": None,
|
||||
"loc": [
|
||||
"body",
|
||||
"user",
|
||||
],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"input": None,
|
||||
"loc": [
|
||||
"body",
|
||||
"importance",
|
||||
],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_put_empty_body(client: TestClient):
|
||||
response = client.put("/items/5", json={})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "item"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "user"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "importance"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_invalid_importance(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"importance": 0,
|
||||
"item": {"name": "Foo", "price": 50.5},
|
||||
"user": {"username": "Dave"},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "importance"],
|
||||
"msg": "Input should be greater than 0",
|
||||
"type": "greater_than",
|
||||
"input": 0,
|
||||
"ctx": {"gt": 0},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"put": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Update Item",
|
||||
"operationId": "update_item_items__item_id__put",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {"title": "Item Id", "type": "integer"},
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_update_item_items__item_id__put"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": ["name", "price"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"User": {
|
||||
"title": "User",
|
||||
"required": ["username"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
"full_name": {
|
||||
"title": "Full Name",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"Body_update_item_items__item_id__put": {
|
||||
"title": "Body_update_item_items__item_id__put",
|
||||
"required": ["item", "user", "importance"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"item": {"$ref": "#/components/schemas/Item"},
|
||||
"user": {"$ref": "#/components/schemas/User"},
|
||||
"importance": {
|
||||
"title": "Importance",
|
||||
"type": "integer",
|
||||
"exclusiveMinimum": 0.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial005_py39"),
|
||||
pytest.param("tutorial005_py310", marks=needs_py310),
|
||||
pytest.param("tutorial005_an_py39"),
|
||||
pytest.param("tutorial005_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.body_multiple_params.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_post_all(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"price": 50.5,
|
||||
"description": "Some Foo",
|
||||
"tax": 0.1,
|
||||
},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"item_id": 5,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"price": 50.5,
|
||||
"description": "Some Foo",
|
||||
"tax": 0.1,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_post_required(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"item": {"name": "Foo", "price": 50.5},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"item_id": 5,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"price": 50.5,
|
||||
"description": None,
|
||||
"tax": None,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_post_no_body(client: TestClient):
|
||||
response = client.put("/items/5", json=None)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": [
|
||||
"body",
|
||||
"item",
|
||||
],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_post_like_not_embeded(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"price": 50.5,
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": [
|
||||
"body",
|
||||
"item",
|
||||
],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_post_missing_required_field_in_item(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5", json={"item": {"name": "Foo"}, "user": {"username": "johndoe"}}
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": {"name": "Foo"},
|
||||
"loc": [
|
||||
"body",
|
||||
"item",
|
||||
"price",
|
||||
],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0",
|
||||
},
|
||||
"openapi": "3.1.0",
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"put": {
|
||||
"operationId": "update_item_items__item_id__put",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "item_id",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "Item Id",
|
||||
"type": "integer",
|
||||
},
|
||||
},
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_update_item_items__item_id__put",
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
"summary": "Update Item",
|
||||
},
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_update_item_items__item_id__put": {
|
||||
"properties": {
|
||||
"item": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
},
|
||||
},
|
||||
"required": ["item"],
|
||||
"title": "Body_update_item_items__item_id__put",
|
||||
"type": "object",
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"price",
|
||||
],
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsList
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
UNTYPED_LIST_SCHEMA = {"type": "array", "items": {}}
|
||||
|
||||
LIST_OF_STR_SCHEMA = {"type": "array", "items": {"type": "string"}}
|
||||
|
||||
SET_OF_STR_SCHEMA = {"type": "array", "items": {"type": "string"}, "uniqueItems": True}
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="mod_name",
|
||||
params=[
|
||||
pytest.param("tutorial001_py39"),
|
||||
pytest.param("tutorial001_py310", marks=needs_py310),
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
pytest.param("tutorial003_py39"),
|
||||
pytest.param("tutorial003_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_mod_name(request: pytest.FixtureRequest):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client(mod_name: str):
|
||||
mod = importlib.import_module(f"docs_src.body_nested_models.{mod_name}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_put_all(client: TestClient, mod_name: str):
|
||||
if mod_name.startswith("tutorial003"):
|
||||
tags_expected = IsList("foo", "bar", check_order=False)
|
||||
else:
|
||||
tags_expected = ["foo", "bar", "foo"]
|
||||
|
||||
response = client.put(
|
||||
"/items/123",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"description": "A very nice Item",
|
||||
"price": 35.4,
|
||||
"tax": 3.2,
|
||||
"tags": ["foo", "bar", "foo"],
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"item_id": 123,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": "A very nice Item",
|
||||
"price": 35.4,
|
||||
"tax": 3.2,
|
||||
"tags": tags_expected,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_put_only_required(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={"name": "Foo", "price": 35.4},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"item_id": 5,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": None,
|
||||
"price": 35.4,
|
||||
"tax": None,
|
||||
"tags": [],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_put_empty_body(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "name"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "price"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_missing_required(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={"description": "A very nice Item"},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "name"],
|
||||
"input": {"description": "A very nice Item"},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "price"],
|
||||
"input": {"description": "A very nice Item"},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient, mod_name: str):
|
||||
tags_schema = {"default": [], "title": "Tags"}
|
||||
if mod_name.startswith("tutorial001"):
|
||||
tags_schema.update(UNTYPED_LIST_SCHEMA)
|
||||
elif mod_name.startswith("tutorial002"):
|
||||
tags_schema.update(LIST_OF_STR_SCHEMA)
|
||||
elif mod_name.startswith("tutorial003"):
|
||||
tags_schema.update(SET_OF_STR_SCHEMA)
|
||||
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"put": {
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "item_id",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "Item Id",
|
||||
"type": "integer",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Update Item",
|
||||
"operationId": "update_item_items__item_id__put",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"type": "number",
|
||||
},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tags": tags_schema,
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"price",
|
||||
],
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
275
tests/test_tutorial/test_body_nested_models/test_tutorial004.py
Normal file
275
tests/test_tutorial/test_body_nested_models/test_tutorial004.py
Normal file
@@ -0,0 +1,275 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsList
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial004_py39"),
|
||||
pytest.param("tutorial004_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.body_nested_models.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_put_all(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/123",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"description": "A very nice Item",
|
||||
"price": 35.4,
|
||||
"tax": 3.2,
|
||||
"tags": ["foo", "bar", "foo"],
|
||||
"image": {"url": "http://example.com/image.png", "name": "example image"},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"item_id": 123,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": "A very nice Item",
|
||||
"price": 35.4,
|
||||
"tax": 3.2,
|
||||
"tags": IsList("foo", "bar", check_order=False),
|
||||
"image": {"url": "http://example.com/image.png", "name": "example image"},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_put_only_required(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={"name": "Foo", "price": 35.4},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"item_id": 5,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": None,
|
||||
"price": 35.4,
|
||||
"tax": None,
|
||||
"tags": [],
|
||||
"image": None,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_put_empty_body(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "name"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "price"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_missing_required_in_item(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={"description": "A very nice Item"},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "name"],
|
||||
"input": {"description": "A very nice Item"},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "price"],
|
||||
"input": {"description": "A very nice Item"},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_missing_required_in_image(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"price": 35.4,
|
||||
"image": {"url": "http://example.com/image.png"},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "image", "name"],
|
||||
"input": {"url": "http://example.com/image.png"},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"put": {
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "item_id",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "Item Id",
|
||||
"type": "integer",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Update Item",
|
||||
"operationId": "update_item_items__item_id__put",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Image": {
|
||||
"properties": {
|
||||
"url": {
|
||||
"title": "Url",
|
||||
"type": "string",
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": ["url", "name"],
|
||||
"title": "Image",
|
||||
"type": "object",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"type": "number",
|
||||
},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": True,
|
||||
},
|
||||
"image": {
|
||||
"anyOf": [
|
||||
{"$ref": "#/components/schemas/Image"},
|
||||
{"type": "null"},
|
||||
],
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"price",
|
||||
],
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
301
tests/test_tutorial/test_body_nested_models/test_tutorial005.py
Normal file
301
tests/test_tutorial/test_body_nested_models/test_tutorial005.py
Normal file
@@ -0,0 +1,301 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsList
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial005_py39"),
|
||||
pytest.param("tutorial005_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.body_nested_models.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_put_all(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/123",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"description": "A very nice Item",
|
||||
"price": 35.4,
|
||||
"tax": 3.2,
|
||||
"tags": ["foo", "bar", "foo"],
|
||||
"image": {"url": "http://example.com/image.png", "name": "example image"},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"item_id": 123,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": "A very nice Item",
|
||||
"price": 35.4,
|
||||
"tax": 3.2,
|
||||
"tags": IsList("foo", "bar", check_order=False),
|
||||
"image": {"url": "http://example.com/image.png", "name": "example image"},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_put_only_required(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={"name": "Foo", "price": 35.4},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"item_id": 5,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": None,
|
||||
"price": 35.4,
|
||||
"tax": None,
|
||||
"tags": [],
|
||||
"image": None,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_put_empty_body(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "name"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "price"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_missing_required_in_item(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={"description": "A very nice Item"},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "name"],
|
||||
"input": {"description": "A very nice Item"},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "price"],
|
||||
"input": {"description": "A very nice Item"},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_missing_required_in_image(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"price": 35.4,
|
||||
"image": {"url": "http://example.com/image.png"},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "image", "name"],
|
||||
"input": {"url": "http://example.com/image.png"},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_wrong_url(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"price": 35.4,
|
||||
"image": {"url": "not a valid url", "name": "example image"},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "image", "url"],
|
||||
"input": "not a valid url",
|
||||
"msg": "Input should be a valid URL, relative URL without a base",
|
||||
"type": "url_parsing",
|
||||
"ctx": {"error": "relative URL without a base"},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"put": {
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "item_id",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "Item Id",
|
||||
"type": "integer",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Update Item",
|
||||
"operationId": "update_item_items__item_id__put",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Image": {
|
||||
"properties": {
|
||||
"url": {
|
||||
"title": "Url",
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"maxLength": 2083,
|
||||
"minLength": 1,
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": ["url", "name"],
|
||||
"title": "Image",
|
||||
"type": "object",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"type": "number",
|
||||
},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": True,
|
||||
},
|
||||
"image": {
|
||||
"anyOf": [
|
||||
{"$ref": "#/components/schemas/Image"},
|
||||
{"type": "null"},
|
||||
],
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"price",
|
||||
],
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
269
tests/test_tutorial/test_body_nested_models/test_tutorial006.py
Normal file
269
tests/test_tutorial/test_body_nested_models/test_tutorial006.py
Normal file
@@ -0,0 +1,269 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsList
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial006_py39"),
|
||||
pytest.param("tutorial006_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.body_nested_models.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_put_all(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/123",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"description": "A very nice Item",
|
||||
"price": 35.4,
|
||||
"tax": 3.2,
|
||||
"tags": ["foo", "bar", "foo"],
|
||||
"images": [
|
||||
{"url": "http://example.com/image.png", "name": "example image"}
|
||||
],
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"item_id": 123,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": "A very nice Item",
|
||||
"price": 35.4,
|
||||
"tax": 3.2,
|
||||
"tags": IsList("foo", "bar", check_order=False),
|
||||
"images": [
|
||||
{"url": "http://example.com/image.png", "name": "example image"}
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_put_only_required(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={"name": "Foo", "price": 35.4},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"item_id": 5,
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": None,
|
||||
"price": 35.4,
|
||||
"tax": None,
|
||||
"tags": [],
|
||||
"images": None,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_put_empty_body(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "name"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "price"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_images_not_list(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"price": 35.4,
|
||||
"images": {"url": "http://example.com/image.png", "name": "example image"},
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "images"],
|
||||
"input": {
|
||||
"url": "http://example.com/image.png",
|
||||
"name": "example image",
|
||||
},
|
||||
"msg": "Input should be a valid list",
|
||||
"type": "list_type",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"put": {
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "item_id",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "Item Id",
|
||||
"type": "integer",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Update Item",
|
||||
"operationId": "update_item_items__item_id__put",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Image": {
|
||||
"properties": {
|
||||
"url": {
|
||||
"title": "Url",
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"maxLength": 2083,
|
||||
"minLength": 1,
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": ["url", "name"],
|
||||
"title": "Image",
|
||||
"type": "object",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"type": "number",
|
||||
},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": True,
|
||||
},
|
||||
"images": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Image",
|
||||
},
|
||||
"type": "array",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
"title": "Images",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"price",
|
||||
],
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
344
tests/test_tutorial/test_body_nested_models/test_tutorial007.py
Normal file
344
tests/test_tutorial/test_body_nested_models/test_tutorial007.py
Normal file
@@ -0,0 +1,344 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial007_py39"),
|
||||
pytest.param("tutorial007_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.body_nested_models.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_post_all(client: TestClient):
|
||||
data = {
|
||||
"name": "Special Offer",
|
||||
"description": "This is a special offer",
|
||||
"price": 38.6,
|
||||
"items": [
|
||||
{
|
||||
"name": "Foo",
|
||||
"description": "A very nice Item",
|
||||
"price": 35.4,
|
||||
"tax": 3.2,
|
||||
"tags": ["foo"],
|
||||
"images": [
|
||||
{
|
||||
"url": "http://example.com/image.png",
|
||||
"name": "example image",
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/offers/",
|
||||
json=data,
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == data
|
||||
|
||||
|
||||
def test_put_only_required(client: TestClient):
|
||||
response = client.post(
|
||||
"/offers/",
|
||||
json={
|
||||
"name": "Special Offer",
|
||||
"price": 38.6,
|
||||
"items": [
|
||||
{
|
||||
"name": "Foo",
|
||||
"price": 35.4,
|
||||
"images": [
|
||||
{
|
||||
"url": "http://example.com/image.png",
|
||||
"name": "example image",
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"name": "Special Offer",
|
||||
"description": None,
|
||||
"price": 38.6,
|
||||
"items": [
|
||||
{
|
||||
"name": "Foo",
|
||||
"description": None,
|
||||
"price": 35.4,
|
||||
"tax": None,
|
||||
"tags": [],
|
||||
"images": [
|
||||
{
|
||||
"url": "http://example.com/image.png",
|
||||
"name": "example image",
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_put_empty_body(client: TestClient):
|
||||
response = client.post(
|
||||
"/offers/",
|
||||
json={},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "name"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "price"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "items"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_missing_required_in_items(client: TestClient):
|
||||
response = client.post(
|
||||
"/offers/",
|
||||
json={
|
||||
"name": "Special Offer",
|
||||
"price": 38.6,
|
||||
"items": [{}],
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "items", 0, "name"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "items", 0, "price"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_missing_required_in_images(client: TestClient):
|
||||
response = client.post(
|
||||
"/offers/",
|
||||
json={
|
||||
"name": "Special Offer",
|
||||
"price": 38.6,
|
||||
"items": [
|
||||
{"name": "Foo", "price": 35.4, "images": [{}]},
|
||||
],
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "items", 0, "images", 0, "url"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "items", 0, "images", 0, "name"],
|
||||
"input": {},
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/offers/": {
|
||||
"post": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Create Offer",
|
||||
"operationId": "create_offer_offers__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Offer",
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Image": {
|
||||
"properties": {
|
||||
"url": {
|
||||
"title": "Url",
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"maxLength": 2083,
|
||||
"minLength": 1,
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": ["url", "name"],
|
||||
"title": "Image",
|
||||
"type": "object",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"type": "number",
|
||||
},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": True,
|
||||
},
|
||||
"images": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Image",
|
||||
},
|
||||
"type": "array",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
"title": "Images",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"price",
|
||||
],
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
},
|
||||
"Offer": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"type": "number",
|
||||
},
|
||||
"items": {
|
||||
"title": "Items",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/Item"},
|
||||
},
|
||||
},
|
||||
"required": ["name", "price", "items"],
|
||||
"title": "Offer",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
157
tests/test_tutorial/test_body_nested_models/test_tutorial008.py
Normal file
157
tests/test_tutorial/test_body_nested_models/test_tutorial008.py
Normal file
@@ -0,0 +1,157 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial008_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.body_nested_models.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_post_body(client: TestClient):
|
||||
data = [
|
||||
{"url": "http://example.com/", "name": "Example"},
|
||||
{"url": "http://fastapi.tiangolo.com/", "name": "FastAPI"},
|
||||
]
|
||||
response = client.post("/images/multiple", json=data)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == data
|
||||
|
||||
|
||||
def test_post_invalid_list_item(client: TestClient):
|
||||
data = [{"url": "not a valid url", "name": "Example"}]
|
||||
response = client.post("/images/multiple", json=data)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", 0, "url"],
|
||||
"input": "not a valid url",
|
||||
"msg": "Input should be a valid URL, relative URL without a base",
|
||||
"type": "url_parsing",
|
||||
"ctx": {"error": "relative URL without a base"},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_post_not_a_list(client: TestClient):
|
||||
data = {"url": "http://example.com/", "name": "Example"}
|
||||
response = client.post("/images/multiple", json=data)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"input": {
|
||||
"name": "Example",
|
||||
"url": "http://example.com/",
|
||||
},
|
||||
"msg": "Input should be a valid list",
|
||||
"type": "list_type",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/images/multiple/": {
|
||||
"post": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Create Multiple Images",
|
||||
"operationId": "create_multiple_images_images_multiple__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"title": "Images",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/Image"},
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Image": {
|
||||
"properties": {
|
||||
"url": {
|
||||
"title": "Url",
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"maxLength": 2083,
|
||||
"minLength": 1,
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": ["url", "name"],
|
||||
"title": "Image",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
207
tests/test_tutorial/test_body_updates/test_tutorial002.py
Normal file
207
tests/test_tutorial/test_body_updates/test_tutorial002.py
Normal file
@@ -0,0 +1,207 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.body_updates.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_get(client: TestClient):
|
||||
response = client.get("/items/baz")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"name": "Baz",
|
||||
"description": None,
|
||||
"price": 50.2,
|
||||
"tax": 10.5,
|
||||
"tags": [],
|
||||
}
|
||||
|
||||
|
||||
def test_patch_all(client: TestClient):
|
||||
response = client.patch(
|
||||
"/items/foo",
|
||||
json={
|
||||
"name": "Fooz",
|
||||
"description": "Item description",
|
||||
"price": 3,
|
||||
"tax": 10.5,
|
||||
"tags": ["tag1", "tag2"],
|
||||
},
|
||||
)
|
||||
assert response.json() == {
|
||||
"name": "Fooz",
|
||||
"description": "Item description",
|
||||
"price": 3,
|
||||
"tax": 10.5,
|
||||
"tags": ["tag1", "tag2"],
|
||||
}
|
||||
|
||||
|
||||
def test_patch_name(client: TestClient):
|
||||
response = client.patch(
|
||||
"/items/bar",
|
||||
json={"name": "Barz"},
|
||||
)
|
||||
assert response.json() == {
|
||||
"name": "Barz",
|
||||
"description": "The bartenders",
|
||||
"price": 62,
|
||||
"tax": 20.2,
|
||||
"tags": [],
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Item",
|
||||
"operationId": "read_item_items__item_id__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {"title": "Item Id", "type": "string"},
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
}
|
||||
],
|
||||
},
|
||||
"patch": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Update Item",
|
||||
"operationId": "update_item_items__item_id__patch",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {"title": "Item Id", "type": "string"},
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item": {
|
||||
"type": "object",
|
||||
"title": "Item",
|
||||
"properties": {
|
||||
"name": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Name",
|
||||
},
|
||||
"description": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Description",
|
||||
},
|
||||
"price": {
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
"title": "Price",
|
||||
},
|
||||
"tax": {"title": "Tax", "type": "number", "default": 10.5},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -1,17 +1,29 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.custom_response.tutorial001_py39 import app
|
||||
|
||||
client = TestClient(app)
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial001_py39"),
|
||||
pytest.param("tutorial010_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.custom_response.{request.param}")
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_get_custom_response():
|
||||
def test_get_custom_response(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == [{"item_id": "Foo"}]
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="mod_name",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial003_py39"),
|
||||
pytest.param("tutorial004_py39"),
|
||||
],
|
||||
)
|
||||
def get_mod_name(request: pytest.FixtureRequest) -> str:
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client(mod_name: str) -> TestClient:
|
||||
mod = importlib.import_module(f"docs_src.custom_response.{mod_name}")
|
||||
return TestClient(mod.app)
|
||||
|
||||
|
||||
html_contents = """
|
||||
<html>
|
||||
<head>
|
||||
<title>Some HTML in here</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Look ma! HTML!</h1>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
|
||||
def test_get_custom_response(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.text == html_contents
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient, mod_name: str):
|
||||
if mod_name.startswith("tutorial003"):
|
||||
response_content = {"application/json": {"schema": {}}}
|
||||
else:
|
||||
response_content = {"text/html": {"schema": {"type": "string"}}}
|
||||
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": response_content,
|
||||
}
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -15,7 +15,7 @@ from tests.utils import needs_py310
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.dataclasses.{request.param}")
|
||||
mod = importlib.import_module(f"docs_src.dataclasses_.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
client.headers.clear()
|
||||
|
||||
@@ -15,7 +15,7 @@ from tests.utils import needs_py310
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.dataclasses.{request.param}")
|
||||
mod = importlib.import_module(f"docs_src.dataclasses_.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
client.headers.clear()
|
||||
|
||||
@@ -14,7 +14,7 @@ from ...utils import needs_py310
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.dataclasses.{request.param}")
|
||||
mod = importlib.import_module(f"docs_src.dataclasses_.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
client.headers.clear()
|
||||
|
||||
0
tests/test_tutorial/test_debugging/__init__.py
Normal file
0
tests/test_tutorial/test_debugging/__init__.py
Normal file
64
tests/test_tutorial/test_debugging/test_tutorial001.py
Normal file
64
tests/test_tutorial/test_debugging/test_tutorial001.py
Normal file
@@ -0,0 +1,64 @@
|
||||
import importlib
|
||||
import runpy
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
MOD_NAME = "docs_src.debugging.tutorial001_py39"
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client():
|
||||
mod = importlib.import_module(MOD_NAME)
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_uvicorn_run_is_not_called_on_import():
|
||||
if sys.modules.get(MOD_NAME):
|
||||
del sys.modules[MOD_NAME] # pragma: no cover
|
||||
with unittest.mock.patch("uvicorn.run") as uvicorn_run_mock:
|
||||
importlib.import_module(MOD_NAME)
|
||||
uvicorn_run_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_get_root(client: TestClient):
|
||||
response = client.get("/")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"hello world": "ba"}
|
||||
|
||||
|
||||
def test_uvicorn_run_called_when_run_as_main(): # Just for coverage
|
||||
if sys.modules.get(MOD_NAME):
|
||||
del sys.modules[MOD_NAME]
|
||||
with unittest.mock.patch("uvicorn.run") as uvicorn_run_mock:
|
||||
runpy.run_module(MOD_NAME, run_name="__main__")
|
||||
|
||||
uvicorn_run_mock.assert_called_once_with(
|
||||
unittest.mock.ANY, host="0.0.0.0", port=8000
|
||||
)
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"summary": "Root",
|
||||
"operationId": "root__get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
@@ -14,6 +13,8 @@ from ...utils import needs_py310
|
||||
pytest.param("tutorial001_py310", marks=needs_py310),
|
||||
pytest.param("tutorial001_an_py39"),
|
||||
pytest.param("tutorial001_an_py310", marks=needs_py310),
|
||||
pytest.param("tutorial001_02_an_py39"),
|
||||
pytest.param("tutorial001_02_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
@@ -69,16 +70,10 @@ def test_openapi_schema(client: TestClient):
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Q",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Q", "type": "string"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
@@ -128,16 +123,10 @@ def test_openapi_schema(client: TestClient):
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Q",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Q", "type": "string"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
@@ -1,7 +1,6 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
@@ -10,6 +9,14 @@ from ...utils import needs_py310
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
pytest.param("tutorial002_an_py39"),
|
||||
pytest.param("tutorial002_an_py310", marks=needs_py310),
|
||||
pytest.param("tutorial003_py39"),
|
||||
pytest.param("tutorial003_py310", marks=needs_py310),
|
||||
pytest.param("tutorial003_an_py39"),
|
||||
pytest.param("tutorial003_an_py310", marks=needs_py310),
|
||||
pytest.param("tutorial004_py39"),
|
||||
pytest.param("tutorial004_py310", marks=needs_py310),
|
||||
pytest.param("tutorial004_an_py39"),
|
||||
@@ -107,16 +114,10 @@ def test_openapi_schema(client: TestClient):
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Q",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Q", "type": "string"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
139
tests/test_tutorial/test_dependencies/test_tutorial005.py
Normal file
139
tests/test_tutorial/test_dependencies/test_tutorial005.py
Normal file
@@ -0,0 +1,139 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial005_py39"),
|
||||
pytest.param("tutorial005_py310", marks=needs_py310),
|
||||
pytest.param("tutorial005_an_py39"),
|
||||
pytest.param("tutorial005_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.dependencies.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"path,cookie,expected_status,expected_response",
|
||||
[
|
||||
(
|
||||
"/items",
|
||||
"from_cookie",
|
||||
200,
|
||||
{"q_or_cookie": "from_cookie"},
|
||||
),
|
||||
(
|
||||
"/items?q=foo",
|
||||
"from_cookie",
|
||||
200,
|
||||
{"q_or_cookie": "foo"},
|
||||
),
|
||||
(
|
||||
"/items",
|
||||
None,
|
||||
200,
|
||||
{"q_or_cookie": None},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_get(path, cookie, expected_status, expected_response, client: TestClient):
|
||||
if cookie is not None:
|
||||
client.cookies.set("last_query", cookie)
|
||||
else:
|
||||
client.cookies.clear()
|
||||
response = client.get(path)
|
||||
assert response.status_code == expected_status
|
||||
assert response.json() == expected_response
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Query",
|
||||
"operationId": "read_query_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Last Query",
|
||||
},
|
||||
"name": "last_query",
|
||||
"in": "cookie",
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
24
tests/test_tutorial/test_dependencies/test_tutorial007.py
Normal file
24
tests/test_tutorial/test_dependencies/test_tutorial007.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import asyncio
|
||||
from contextlib import asynccontextmanager
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from docs_src.dependencies.tutorial007_py39 import get_db
|
||||
|
||||
|
||||
def test_get_db(): # Just for coverage
|
||||
async def test_async_gen():
|
||||
cm = asynccontextmanager(get_db)
|
||||
async with cm() as db_session:
|
||||
return db_session
|
||||
|
||||
dbsession_moock = Mock()
|
||||
|
||||
with patch(
|
||||
"docs_src.dependencies.tutorial007_py39.DBSession",
|
||||
return_value=dbsession_moock,
|
||||
create=True,
|
||||
):
|
||||
value = asyncio.run(test_async_gen())
|
||||
|
||||
assert value is dbsession_moock
|
||||
dbsession_moock.close.assert_called_once()
|
||||
58
tests/test_tutorial/test_dependencies/test_tutorial008.py
Normal file
58
tests/test_tutorial/test_dependencies/test_tutorial008.py
Normal file
@@ -0,0 +1,58 @@
|
||||
import importlib
|
||||
from types import ModuleType
|
||||
from typing import Annotated, Any
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="module",
|
||||
params=[
|
||||
"tutorial008_py39",
|
||||
# Fails with `NameError: name 'DepA' is not defined`
|
||||
pytest.param("tutorial008_an_py39", marks=pytest.mark.xfail),
|
||||
],
|
||||
)
|
||||
def get_module(request: pytest.FixtureRequest):
|
||||
mod_name = f"docs_src.dependencies.{request.param}"
|
||||
mod = importlib.import_module(mod_name)
|
||||
return mod
|
||||
|
||||
|
||||
def test_get_db(module: ModuleType):
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/")
|
||||
def read_root(c: Annotated[Any, Depends(module.dependency_c)]):
|
||||
return {"c": str(c)}
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
a_mock = Mock()
|
||||
b_mock = Mock()
|
||||
c_mock = Mock()
|
||||
|
||||
with (
|
||||
patch(
|
||||
f"{module.__name__}.generate_dep_a",
|
||||
return_value=a_mock,
|
||||
create=True,
|
||||
),
|
||||
patch(
|
||||
f"{module.__name__}.generate_dep_b",
|
||||
return_value=b_mock,
|
||||
create=True,
|
||||
),
|
||||
patch(
|
||||
f"{module.__name__}.generate_dep_c",
|
||||
return_value=c_mock,
|
||||
create=True,
|
||||
),
|
||||
):
|
||||
response = client.get("/")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"c": str(c_mock)}
|
||||
29
tests/test_tutorial/test_dependencies/test_tutorial010.py
Normal file
29
tests/test_tutorial/test_dependencies/test_tutorial010.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from typing import Annotated, Any
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.dependencies.tutorial010_py39 import get_db
|
||||
|
||||
|
||||
def test_get_db():
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/")
|
||||
def read_root(c: Annotated[Any, Depends(get_db)]):
|
||||
return {"c": str(c)}
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
dbsession_mock = Mock()
|
||||
|
||||
with patch(
|
||||
"docs_src.dependencies.tutorial010_py39.DBSession",
|
||||
return_value=dbsession_mock,
|
||||
create=True,
|
||||
):
|
||||
response = client.get("/")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"c": str(dbsession_mock)}
|
||||
120
tests/test_tutorial/test_dependencies/test_tutorial011.py
Normal file
120
tests/test_tutorial/test_dependencies/test_tutorial011.py
Normal file
@@ -0,0 +1,120 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
"tutorial011_py39",
|
||||
pytest.param("tutorial011_an_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.dependencies.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"path,expected_status,expected_response",
|
||||
[
|
||||
(
|
||||
"/query-checker/",
|
||||
200,
|
||||
{"fixed_content_in_query": False},
|
||||
),
|
||||
(
|
||||
"/query-checker/?q=qwerty",
|
||||
200,
|
||||
{"fixed_content_in_query": False},
|
||||
),
|
||||
(
|
||||
"/query-checker/?q=foobar",
|
||||
200,
|
||||
{"fixed_content_in_query": True},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_get(path, expected_status, expected_response, client: TestClient):
|
||||
response = client.get(path)
|
||||
assert response.status_code == expected_status
|
||||
assert response.json() == expected_response
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/query-checker/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Query Check",
|
||||
"operationId": "read_query_check_query_checker__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
0
tests/test_tutorial/test_encoder/__init__.py
Normal file
0
tests/test_tutorial/test_encoder/__init__.py
Normal file
208
tests/test_tutorial/test_encoder/test_tutorial001.py
Normal file
208
tests/test_tutorial/test_encoder/test_tutorial001.py
Normal file
@@ -0,0 +1,208 @@
|
||||
import importlib
|
||||
from types import ModuleType
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="mod",
|
||||
params=[
|
||||
pytest.param("tutorial001_py39"),
|
||||
pytest.param("tutorial001_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_module(request: pytest.FixtureRequest):
|
||||
module = importlib.import_module(f"docs_src.encoder.{request.param}")
|
||||
return module
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_put(client: TestClient, mod: ModuleType):
|
||||
fake_db = mod.fake_db
|
||||
|
||||
response = client.put(
|
||||
"/items/123",
|
||||
json={
|
||||
"title": "Foo",
|
||||
"timestamp": "2023-01-01T12:00:00",
|
||||
"description": "An optional description",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert "123" in fake_db
|
||||
assert fake_db["123"] == {
|
||||
"title": "Foo",
|
||||
"timestamp": "2023-01-01T12:00:00",
|
||||
"description": "An optional description",
|
||||
}
|
||||
|
||||
|
||||
def test_put_invalid_data(client: TestClient, mod: ModuleType):
|
||||
fake_db = mod.fake_db
|
||||
|
||||
response = client.put(
|
||||
"/items/345",
|
||||
json={
|
||||
"title": "Foo",
|
||||
"timestamp": "not a date",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "timestamp"],
|
||||
"msg": "Input should be a valid datetime or date, invalid character in year",
|
||||
"type": "datetime_from_date_parsing",
|
||||
"input": "not a date",
|
||||
"ctx": {"error": "invalid character in year"},
|
||||
}
|
||||
]
|
||||
}
|
||||
assert "345" not in fake_db
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{id}": {
|
||||
"put": {
|
||||
"operationId": "update_item_items__id__put",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "id",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "Id",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
"summary": "Update Item",
|
||||
},
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
"title": "Description",
|
||||
},
|
||||
"timestamp": {
|
||||
"format": "date-time",
|
||||
"title": "Timestamp",
|
||||
"type": "string",
|
||||
},
|
||||
"title": {
|
||||
"title": "Title",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"title",
|
||||
"timestamp",
|
||||
],
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsList
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial001_py39"),
|
||||
pytest.param("tutorial001_py310", marks=needs_py310),
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.extra_models.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_post(client: TestClient):
|
||||
response = client.post(
|
||||
"/user/",
|
||||
json={
|
||||
"username": "johndoe",
|
||||
"password": "secret",
|
||||
"email": "johndoe@example.com",
|
||||
"full_name": "John Doe",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"username": "johndoe",
|
||||
"email": "johndoe@example.com",
|
||||
"full_name": "John Doe",
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/user/": {
|
||||
"post": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/UserOut",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Create User",
|
||||
"operationId": "create_user_user__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/UserIn"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"UserIn": {
|
||||
"title": "UserIn",
|
||||
"required": IsList(
|
||||
"username", "password", "email", check_order=False
|
||||
),
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
"password": {"title": "Password", "type": "string"},
|
||||
"email": {
|
||||
"title": "Email",
|
||||
"type": "string",
|
||||
"format": "email",
|
||||
},
|
||||
"full_name": {
|
||||
"title": "Full Name",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"UserOut": {
|
||||
"title": "UserOut",
|
||||
"required": ["username", "email"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
"email": {
|
||||
"title": "Email",
|
||||
"type": "string",
|
||||
"format": "email",
|
||||
},
|
||||
"full_name": {
|
||||
"title": "Full Name",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -1,9 +1,20 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.first_steps.tutorial001_py39 import app
|
||||
|
||||
client = TestClient(app)
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
"tutorial001_py39",
|
||||
"tutorial003_py39",
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.first_steps.{request.param}")
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -13,13 +24,13 @@ client = TestClient(app)
|
||||
("/nonexistent", 404, {"detail": "Not Found"}),
|
||||
],
|
||||
)
|
||||
def test_get_path(path, expected_status, expected_response):
|
||||
def test_get_path(client: TestClient, path, expected_status, expected_response):
|
||||
response = client.get(path)
|
||||
assert response.status_code == expected_status
|
||||
assert response.json() == expected_response
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
142
tests/test_tutorial/test_generate_clients/test_tutorial001.py
Normal file
142
tests/test_tutorial/test_generate_clients/test_tutorial001.py
Normal file
@@ -0,0 +1,142 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial001_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.generate_clients.{request.param}")
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_post_items(client: TestClient):
|
||||
response = client.post("/items/", json={"name": "Foo", "price": 5})
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"message": "item received"}
|
||||
|
||||
|
||||
def test_get_items(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == [
|
||||
{"name": "Plumbus", "price": 3},
|
||||
{"name": "Portal Gun", "price": 9001},
|
||||
]
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"summary": "Get Items",
|
||||
"operationId": "get_items_items__get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"title": "Response Get Items Items Get",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/Item"},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
"post": {
|
||||
"summary": "Create Item",
|
||||
"operationId": "create_item_items__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResponseMessage"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": ["name", "price"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
},
|
||||
},
|
||||
"ResponseMessage": {
|
||||
"title": "ResponseMessage",
|
||||
"required": ["message"],
|
||||
"type": "object",
|
||||
"properties": {"message": {"title": "Message", "type": "string"}},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
187
tests/test_tutorial/test_generate_clients/test_tutorial002.py
Normal file
187
tests/test_tutorial/test_generate_clients/test_tutorial002.py
Normal file
@@ -0,0 +1,187 @@
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.generate_clients.tutorial002_py39 import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
def test_post_items():
|
||||
response = client.post("/items/", json={"name": "Foo", "price": 5})
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"message": "Item received"}
|
||||
|
||||
|
||||
def test_post_users():
|
||||
response = client.post(
|
||||
"/users/", json={"username": "Foo", "email": "foo@example.com"}
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"message": "User received"}
|
||||
|
||||
|
||||
def test_get_items():
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == [
|
||||
{"name": "Plumbus", "price": 3},
|
||||
{"name": "Portal Gun", "price": 9001},
|
||||
]
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"tags": ["items"],
|
||||
"summary": "Get Items",
|
||||
"operationId": "get_items_items__get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"title": "Response Get Items Items Get",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/Item"},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
"post": {
|
||||
"tags": ["items"],
|
||||
"summary": "Create Item",
|
||||
"operationId": "create_item_items__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResponseMessage"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"/users/": {
|
||||
"post": {
|
||||
"tags": ["users"],
|
||||
"summary": "Create User",
|
||||
"operationId": "create_user_users__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/User"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResponseMessage"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": ["name", "price"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
},
|
||||
},
|
||||
"ResponseMessage": {
|
||||
"title": "ResponseMessage",
|
||||
"required": ["message"],
|
||||
"type": "object",
|
||||
"properties": {"message": {"title": "Message", "type": "string"}},
|
||||
},
|
||||
"User": {
|
||||
"title": "User",
|
||||
"required": ["username", "email"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
"email": {"title": "Email", "type": "string"},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
230
tests/test_tutorial/test_generate_clients/test_tutorial004.py
Normal file
230
tests/test_tutorial/test_generate_clients/test_tutorial004.py
Normal file
@@ -0,0 +1,230 @@
|
||||
import importlib
|
||||
import json
|
||||
import pathlib
|
||||
from unittest.mock import patch
|
||||
|
||||
from docs_src.generate_clients import tutorial003_py39
|
||||
|
||||
|
||||
def test_remove_tags(tmp_path: pathlib.Path):
|
||||
tmp_file = tmp_path / "openapi.json"
|
||||
openapi_json = tutorial003_py39.app.openapi()
|
||||
tmp_file.write_text(json.dumps(openapi_json))
|
||||
|
||||
with patch("pathlib.Path", return_value=tmp_file):
|
||||
importlib.import_module("docs_src.generate_clients.tutorial004_py39")
|
||||
|
||||
modified_openapi = json.loads(tmp_file.read_text())
|
||||
assert modified_openapi == {
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"type": "number",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"price",
|
||||
],
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
},
|
||||
"ResponseMessage": {
|
||||
"properties": {
|
||||
"message": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"message",
|
||||
],
|
||||
"title": "ResponseMessage",
|
||||
"type": "object",
|
||||
},
|
||||
"User": {
|
||||
"properties": {
|
||||
"email": {
|
||||
"title": "Email",
|
||||
"type": "string",
|
||||
},
|
||||
"username": {
|
||||
"title": "Username",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"username",
|
||||
"email",
|
||||
],
|
||||
"title": "User",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0",
|
||||
},
|
||||
"openapi": "3.1.0",
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"operationId": "get_items",
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
},
|
||||
"title": "Response Items-Get Items",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
},
|
||||
"summary": "Get Items",
|
||||
"tags": [
|
||||
"items",
|
||||
],
|
||||
},
|
||||
"post": {
|
||||
"operationId": "create_item",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResponseMessage",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
"summary": "Create Item",
|
||||
"tags": [
|
||||
"items",
|
||||
],
|
||||
},
|
||||
},
|
||||
"/users/": {
|
||||
"post": {
|
||||
"operationId": "create_user",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/User",
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ResponseMessage",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
"summary": "Create User",
|
||||
"tags": [
|
||||
"users",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
0
tests/test_tutorial/test_graphql/__init__.py
Normal file
0
tests/test_tutorial/test_graphql/__init__.py
Normal file
70
tests/test_tutorial/test_graphql/test_tutorial001.py
Normal file
70
tests/test_tutorial/test_graphql/test_tutorial001.py
Normal file
@@ -0,0 +1,70 @@
|
||||
import warnings
|
||||
|
||||
import pytest
|
||||
from starlette.testclient import TestClient
|
||||
|
||||
warnings.filterwarnings(
|
||||
"ignore",
|
||||
message=r"The 'lia' package has been renamed to 'cross_web'\..*",
|
||||
category=DeprecationWarning,
|
||||
)
|
||||
|
||||
from docs_src.graphql_.tutorial001_py39 import app # noqa: E402
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client() -> TestClient:
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
def test_query(client: TestClient):
|
||||
response = client.post("/graphql", json={"query": "{ user { name, age } }"})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"data": {"user": {"name": "Patrick", "age": 100}}}
|
||||
|
||||
|
||||
def test_openapi(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0",
|
||||
},
|
||||
"openapi": "3.1.0",
|
||||
"paths": {
|
||||
"/graphql": {
|
||||
"get": {
|
||||
"operationId": "handle_http_get_graphql_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
},
|
||||
},
|
||||
"description": "The GraphiQL integrated development environment.",
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found if GraphiQL or query via GET are not enabled.",
|
||||
},
|
||||
},
|
||||
"summary": "Handle Http Get",
|
||||
},
|
||||
"post": {
|
||||
"operationId": "handle_http_post_graphql_post",
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
},
|
||||
"summary": "Handle Http Post",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,45 +1,41 @@
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.custom_response.tutorial004_py39 import app
|
||||
from docs_src.metadata.tutorial002_py39 import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
html_contents = """
|
||||
<html>
|
||||
<head>
|
||||
<title>Some HTML in here</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Look ma! HTML!</h1>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
|
||||
def test_get_custom_response():
|
||||
def test_items():
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.text == html_contents
|
||||
assert response.json() == [{"name": "Foo"}]
|
||||
|
||||
|
||||
def test_get_openapi_json_default_url():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 404, response.text
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
response = client.get("/api/v1/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0",
|
||||
},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"text/html": {"schema": {"type": "string"}}},
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
}
|
||||
}
|
||||
},
|
||||
53
tests/test_tutorial/test_metadata/test_tutorial003.py
Normal file
53
tests/test_tutorial/test_metadata/test_tutorial003.py
Normal file
@@ -0,0 +1,53 @@
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.metadata.tutorial003_py39 import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
def test_items():
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == [{"name": "Foo"}]
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0",
|
||||
},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_swagger_ui_default_url():
|
||||
response = client.get("/docs")
|
||||
assert response.status_code == 404, response.text
|
||||
|
||||
|
||||
def test_swagger_ui_custom_url():
|
||||
response = client.get("/documentation")
|
||||
assert response.status_code == 200, response.text
|
||||
assert "<title>FastAPI - Swagger UI</title>" in response.text
|
||||
|
||||
|
||||
def test_redoc_ui_default_url():
|
||||
response = client.get("/redoc")
|
||||
assert response.status_code == 404, response.text
|
||||
0
tests/test_tutorial/test_middleware/__init__.py
Normal file
0
tests/test_tutorial/test_middleware/__init__.py
Normal file
24
tests/test_tutorial/test_middleware/test_tutorial001.py
Normal file
24
tests/test_tutorial/test_middleware/test_tutorial001.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.middleware.tutorial001_py39 import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
def test_response_headers():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert "X-Process-Time" in response.headers
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0",
|
||||
},
|
||||
"paths": {},
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsList
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial001_py39"),
|
||||
pytest.param("tutorial001_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest) -> TestClient:
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.path_operation_configuration.{request.param}"
|
||||
)
|
||||
return TestClient(mod.app)
|
||||
|
||||
|
||||
def test_post_items(client: TestClient):
|
||||
response = client.post(
|
||||
"/items/",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"description": "Item description",
|
||||
"price": 42.0,
|
||||
"tax": 3.2,
|
||||
"tags": ["bar", "baz"],
|
||||
},
|
||||
)
|
||||
assert response.status_code == 201, response.text
|
||||
assert response.json() == {
|
||||
"name": "Foo",
|
||||
"description": "Item description",
|
||||
"price": 42.0,
|
||||
"tax": 3.2,
|
||||
"tags": IsList("bar", "baz", check_order=False),
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"post": {
|
||||
"summary": "Create Item",
|
||||
"operationId": "create_item_items__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
"title": "Description",
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"type": "number",
|
||||
},
|
||||
"tags": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"type": "string",
|
||||
},
|
||||
"title": "Tags",
|
||||
"type": "array",
|
||||
"uniqueItems": True,
|
||||
},
|
||||
"tax": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
"title": "Tax",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"price",
|
||||
],
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsList
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest) -> TestClient:
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.path_operation_configuration.{request.param}"
|
||||
)
|
||||
return TestClient(mod.app)
|
||||
|
||||
|
||||
def test_post_items(client: TestClient):
|
||||
response = client.post(
|
||||
"/items/",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"description": "Item description",
|
||||
"price": 42.0,
|
||||
"tax": 3.2,
|
||||
"tags": ["bar", "baz"],
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"name": "Foo",
|
||||
"description": "Item description",
|
||||
"price": 42.0,
|
||||
"tax": 3.2,
|
||||
"tags": IsList("bar", "baz", check_order=False),
|
||||
}
|
||||
|
||||
|
||||
def test_get_items(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == [{"name": "Foo", "price": 42}]
|
||||
|
||||
|
||||
def test_get_users(client: TestClient):
|
||||
response = client.get("/users/")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == [{"username": "johndoe"}]
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"tags": ["items"],
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
},
|
||||
"post": {
|
||||
"tags": ["items"],
|
||||
"summary": "Create Item",
|
||||
"operationId": "create_item_items__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"/users/": {
|
||||
"get": {
|
||||
"tags": ["users"],
|
||||
"summary": "Read Users",
|
||||
"operationId": "read_users_users__get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
"title": "Description",
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"type": "number",
|
||||
},
|
||||
"tags": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"type": "string",
|
||||
},
|
||||
"title": "Tags",
|
||||
"type": "array",
|
||||
"uniqueItems": True,
|
||||
},
|
||||
"tax": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
"title": "Tax",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"price",
|
||||
],
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
import importlib
|
||||
from textwrap import dedent
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsList
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
DESCRIPTIONS = {
|
||||
"tutorial003": "Create an item with all the information, name, description, price, tax and a set of unique tags",
|
||||
"tutorial004": dedent("""
|
||||
Create an item with all the information:
|
||||
|
||||
- **name**: each item must have a name
|
||||
- **description**: a long description
|
||||
- **price**: required
|
||||
- **tax**: if the item doesn't have tax, you can omit this
|
||||
- **tags**: a set of unique tag strings for this item
|
||||
""").strip(),
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="mod_name",
|
||||
params=[
|
||||
pytest.param("tutorial003_py39"),
|
||||
pytest.param("tutorial003_py310", marks=needs_py310),
|
||||
pytest.param("tutorial004_py39"),
|
||||
pytest.param("tutorial004_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_mod_name(request: pytest.FixtureRequest) -> str:
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client(mod_name: str) -> TestClient:
|
||||
mod = importlib.import_module(f"docs_src.path_operation_configuration.{mod_name}")
|
||||
return TestClient(mod.app)
|
||||
|
||||
|
||||
def test_post_items(client: TestClient):
|
||||
response = client.post(
|
||||
"/items/",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"description": "Item description",
|
||||
"price": 42.0,
|
||||
"tax": 3.2,
|
||||
"tags": ["bar", "baz"],
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"name": "Foo",
|
||||
"description": "Item description",
|
||||
"price": 42.0,
|
||||
"tax": 3.2,
|
||||
"tags": IsList("bar", "baz", check_order=False),
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient, mod_name: str):
|
||||
mod_name = mod_name[:11]
|
||||
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"post": {
|
||||
"summary": "Create an item",
|
||||
"description": DESCRIPTIONS[mod_name],
|
||||
"operationId": "create_item_items__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
"title": "Description",
|
||||
},
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"type": "number",
|
||||
},
|
||||
"tags": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"type": "string",
|
||||
},
|
||||
"title": "Tags",
|
||||
"type": "array",
|
||||
"uniqueItems": True,
|
||||
},
|
||||
"tax": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
"title": "Tax",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"price",
|
||||
],
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
116
tests/test_tutorial/test_path_params/test_tutorial001.py
Normal file
116
tests/test_tutorial/test_path_params/test_tutorial001.py
Normal file
@@ -0,0 +1,116 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.path_params.tutorial001_py39 import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("item_id", "expected_response"),
|
||||
[
|
||||
(1, {"item_id": "1"}),
|
||||
("alice", {"item_id": "alice"}),
|
||||
],
|
||||
)
|
||||
def test_get_items(item_id, expected_response):
|
||||
response = client.get(f"/items/{item_id}")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == expected_response
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"get": {
|
||||
"operationId": "read_item_items__item_id__get",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "item_id",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "Item Id",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
"summary": "Read Item",
|
||||
},
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
124
tests/test_tutorial/test_path_params/test_tutorial002.py
Normal file
124
tests/test_tutorial/test_path_params/test_tutorial002.py
Normal file
@@ -0,0 +1,124 @@
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.path_params.tutorial002_py39 import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
def test_get_items():
|
||||
response = client.get("/items/1")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"item_id": 1}
|
||||
|
||||
|
||||
def test_get_items_invalid_id():
|
||||
response = client.get("/items/item1")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": "item1",
|
||||
"loc": ["path", "item_id"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"type": "int_parsing",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"get": {
|
||||
"operationId": "read_item_items__item_id__get",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "item_id",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "Item Id",
|
||||
"type": "integer",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
"summary": "Read Item",
|
||||
},
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
133
tests/test_tutorial/test_path_params/test_tutorial003.py
Normal file
133
tests/test_tutorial/test_path_params/test_tutorial003.py
Normal file
@@ -0,0 +1,133 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.path_params.tutorial003_py39 import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("user_id", "expected_response"),
|
||||
[
|
||||
("me", {"user_id": "the current user"}),
|
||||
("alice", {"user_id": "alice"}),
|
||||
],
|
||||
)
|
||||
def test_get_users(user_id: str, expected_response: dict):
|
||||
response = client.get(f"/users/{user_id}")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == expected_response
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/users/me": {
|
||||
"get": {
|
||||
"operationId": "read_user_me_users_me_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
},
|
||||
"summary": "Read User Me",
|
||||
},
|
||||
},
|
||||
"/users/{user_id}": {
|
||||
"get": {
|
||||
"operationId": "read_user_users__user_id__get",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "user_id",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "User Id",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
"summary": "Read User",
|
||||
},
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
44
tests/test_tutorial/test_path_params/test_tutorial003b.py
Normal file
44
tests/test_tutorial/test_path_params/test_tutorial003b.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import asyncio
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.path_params.tutorial003b_py39 import app, read_users2
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
def test_get_users():
|
||||
response = client.get("/users")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == ["Rick", "Morty"]
|
||||
|
||||
|
||||
def test_read_users2(): # Just for coverage
|
||||
assert asyncio.run(read_users2()) == ["Bean", "Elfo"]
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/users": {
|
||||
"get": {
|
||||
"operationId": "read_users2_users_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
},
|
||||
"summary": "Read Users2",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial001_py39"),
|
||||
pytest.param("tutorial001_py310", marks=needs_py310),
|
||||
pytest.param("tutorial001_an_py39"),
|
||||
pytest.param("tutorial001_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest) -> TestClient:
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.path_params_numeric_validations.{request.param}"
|
||||
)
|
||||
return TestClient(mod.app)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"path,expected_response",
|
||||
[
|
||||
("/items/42", {"item_id": 42}),
|
||||
("/items/123?item-query=somequery", {"item_id": 123, "q": "somequery"}),
|
||||
],
|
||||
)
|
||||
def test_read_items(client: TestClient, path, expected_response):
|
||||
response = client.get(path)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == expected_response
|
||||
|
||||
|
||||
def test_read_items_invalid_item_id(client: TestClient):
|
||||
response = client.get("/items/invalid_id")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["path", "item_id"],
|
||||
"input": "invalid_id",
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"type": "int_parsing",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"get": {
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__item_id__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "The ID of the item to get",
|
||||
"type": "integer",
|
||||
},
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
"title": "Item-Query",
|
||||
},
|
||||
"name": "item-query",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_an_py39"),
|
||||
pytest.param("tutorial003_py39"),
|
||||
pytest.param("tutorial003_an_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest) -> TestClient:
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.path_params_numeric_validations.{request.param}"
|
||||
)
|
||||
return TestClient(mod.app)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"path,expected_response",
|
||||
[
|
||||
("/items/42?q=", {"item_id": 42}),
|
||||
("/items/123?q=somequery", {"item_id": 123, "q": "somequery"}),
|
||||
],
|
||||
)
|
||||
def test_read_items(client: TestClient, path, expected_response):
|
||||
response = client.get(path)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == expected_response
|
||||
|
||||
|
||||
def test_read_items_invalid_item_id(client: TestClient):
|
||||
response = client.get("/items/invalid_id?q=somequery")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["path", "item_id"],
|
||||
"input": "invalid_id",
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"type": "int_parsing",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_read_items_missing_q(client: TestClient):
|
||||
response = client.get("/items/42")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "q"],
|
||||
"input": None,
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"get": {
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__item_id__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "The ID of the item to get",
|
||||
"type": "integer",
|
||||
},
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
},
|
||||
{
|
||||
"required": True,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial004_py39"),
|
||||
pytest.param("tutorial004_an_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest) -> TestClient:
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.path_params_numeric_validations.{request.param}"
|
||||
)
|
||||
return TestClient(mod.app)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"path,expected_response",
|
||||
[
|
||||
("/items/42?q=", {"item_id": 42}),
|
||||
("/items/1?q=somequery", {"item_id": 1, "q": "somequery"}),
|
||||
],
|
||||
)
|
||||
def test_read_items(client: TestClient, path, expected_response):
|
||||
response = client.get(path)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == expected_response
|
||||
|
||||
|
||||
def test_read_items_non_int_item_id(client: TestClient):
|
||||
response = client.get("/items/invalid_id?q=somequery")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["path", "item_id"],
|
||||
"input": "invalid_id",
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"type": "int_parsing",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_read_items_item_id_less_than_one(client: TestClient):
|
||||
response = client.get("/items/0?q=somequery")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["path", "item_id"],
|
||||
"input": "0",
|
||||
"msg": "Input should be greater than or equal to 1",
|
||||
"type": "greater_than_equal",
|
||||
"ctx": {"ge": 1},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_read_items_missing_q(client: TestClient):
|
||||
response = client.get("/items/42")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "q"],
|
||||
"input": None,
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"get": {
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__item_id__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "The ID of the item to get",
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
},
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
},
|
||||
{
|
||||
"required": True,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial005_py39"),
|
||||
pytest.param("tutorial005_an_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest) -> TestClient:
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.path_params_numeric_validations.{request.param}"
|
||||
)
|
||||
return TestClient(mod.app)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"path,expected_response",
|
||||
[
|
||||
("/items/1?q=", {"item_id": 1}),
|
||||
("/items/1000?q=somequery", {"item_id": 1000, "q": "somequery"}),
|
||||
],
|
||||
)
|
||||
def test_read_items(client: TestClient, path, expected_response):
|
||||
response = client.get(path)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == expected_response
|
||||
|
||||
|
||||
def test_read_items_non_int_item_id(client: TestClient):
|
||||
response = client.get("/items/invalid_id?q=somequery")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["path", "item_id"],
|
||||
"input": "invalid_id",
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"type": "int_parsing",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_read_items_item_id_less_than_one(client: TestClient):
|
||||
response = client.get("/items/0?q=somequery")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["path", "item_id"],
|
||||
"input": "0",
|
||||
"msg": "Input should be greater than 0",
|
||||
"type": "greater_than",
|
||||
"ctx": {"gt": 0},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_read_items_item_id_greater_than_one_thousand(client: TestClient):
|
||||
response = client.get("/items/1001?q=somequery")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["path", "item_id"],
|
||||
"input": "1001",
|
||||
"msg": "Input should be less than or equal to 1000",
|
||||
"type": "less_than_equal",
|
||||
"ctx": {"le": 1000},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_read_items_missing_q(client: TestClient):
|
||||
response = client.get("/items/42")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "q"],
|
||||
"input": None,
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"get": {
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__item_id__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "The ID of the item to get",
|
||||
"type": "integer",
|
||||
"exclusiveMinimum": 0,
|
||||
"maximum": 1000,
|
||||
},
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
},
|
||||
{
|
||||
"required": True,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial006_py39"),
|
||||
pytest.param("tutorial006_an_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest) -> TestClient:
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.path_params_numeric_validations.{request.param}"
|
||||
)
|
||||
return TestClient(mod.app)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"path,expected_response",
|
||||
[
|
||||
(
|
||||
"/items/0?q=&size=0.1",
|
||||
{"item_id": 0, "size": 0.1},
|
||||
),
|
||||
(
|
||||
"/items/1000?q=somequery&size=10.4",
|
||||
{"item_id": 1000, "q": "somequery", "size": 10.4},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_read_items(client: TestClient, path, expected_response):
|
||||
response = client.get(path)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == expected_response
|
||||
|
||||
|
||||
def test_read_items_item_id_less_than_zero(client: TestClient):
|
||||
response = client.get("/items/-1?q=somequery&size=5")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["path", "item_id"],
|
||||
"input": "-1",
|
||||
"msg": "Input should be greater than or equal to 0",
|
||||
"type": "greater_than_equal",
|
||||
"ctx": {"ge": 0},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_read_items_item_id_greater_than_one_thousand(client: TestClient):
|
||||
response = client.get("/items/1001?q=somequery&size=5")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["path", "item_id"],
|
||||
"input": "1001",
|
||||
"msg": "Input should be less than or equal to 1000",
|
||||
"type": "less_than_equal",
|
||||
"ctx": {"le": 1000},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_read_items_size_too_small(client: TestClient):
|
||||
response = client.get("/items/1?q=somequery&size=0.0")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "size"],
|
||||
"input": "0.0",
|
||||
"msg": "Input should be greater than 0",
|
||||
"type": "greater_than",
|
||||
"ctx": {"gt": 0.0},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_read_items_size_too_large(client: TestClient):
|
||||
response = client.get("/items/1?q=somequery&size=10.5")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "size"],
|
||||
"input": "10.5",
|
||||
"msg": "Input should be less than 10.5",
|
||||
"type": "less_than",
|
||||
"ctx": {"lt": 10.5},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"get": {
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__item_id__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "The ID of the item to get",
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 1000,
|
||||
},
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
},
|
||||
{
|
||||
"required": True,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "size",
|
||||
"required": True,
|
||||
"schema": {
|
||||
"exclusiveMaximum": 10.5,
|
||||
"exclusiveMinimum": 0,
|
||||
"title": "Size",
|
||||
"type": "number",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError",
|
||||
},
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
},
|
||||
],
|
||||
},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type",
|
||||
],
|
||||
"title": "ValidationError",
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
0
tests/test_tutorial/test_python_types/__init__.py
Normal file
0
tests/test_tutorial/test_python_types/__init__.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import runpy
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"module_name",
|
||||
[
|
||||
"tutorial001_py39",
|
||||
"tutorial002_py39",
|
||||
],
|
||||
)
|
||||
def test_run_module(module_name: str):
|
||||
with patch("builtins.print") as mock_print:
|
||||
runpy.run_module(f"docs_src.python_types.{module_name}", run_name="__main__")
|
||||
|
||||
mock_print.assert_called_with("John Doe")
|
||||
12
tests/test_tutorial/test_python_types/test_tutorial003.py
Normal file
12
tests/test_tutorial/test_python_types/test_tutorial003.py
Normal file
@@ -0,0 +1,12 @@
|
||||
import pytest
|
||||
|
||||
from docs_src.python_types.tutorial003_py39 import get_name_with_age
|
||||
|
||||
|
||||
def test_get_name_with_age_pass_int():
|
||||
with pytest.raises(TypeError):
|
||||
get_name_with_age("John", 30)
|
||||
|
||||
|
||||
def test_get_name_with_age_pass_str():
|
||||
assert get_name_with_age("John", "30") == "John is this old: 30"
|
||||
@@ -0,0 +1,5 @@
|
||||
from docs_src.python_types.tutorial004_py39 import get_name_with_age
|
||||
|
||||
|
||||
def test_get_name_with_age_pass_int():
|
||||
assert get_name_with_age("John", 30) == "John is this old: 30"
|
||||
12
tests/test_tutorial/test_python_types/test_tutorial005.py
Normal file
12
tests/test_tutorial/test_python_types/test_tutorial005.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from docs_src.python_types.tutorial005_py39 import get_items
|
||||
|
||||
|
||||
def test_get_items():
|
||||
res = get_items(
|
||||
"item_a",
|
||||
"item_b",
|
||||
"item_c",
|
||||
"item_d",
|
||||
"item_e",
|
||||
)
|
||||
assert res == ("item_a", "item_b", "item_c", "item_d", "item_e")
|
||||
16
tests/test_tutorial/test_python_types/test_tutorial006.py
Normal file
16
tests/test_tutorial/test_python_types/test_tutorial006.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
from docs_src.python_types.tutorial006_py39 import process_items
|
||||
|
||||
|
||||
def test_process_items():
|
||||
with patch("builtins.print") as mock_print:
|
||||
process_items(["item_a", "item_b", "item_c"])
|
||||
|
||||
assert mock_print.call_count == 3
|
||||
call_args = [arg.args for arg in mock_print.call_args_list]
|
||||
assert call_args == [
|
||||
("item_a",),
|
||||
("item_b",),
|
||||
("item_c",),
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
from docs_src.python_types.tutorial007_py39 import process_items
|
||||
|
||||
|
||||
def test_process_items():
|
||||
items_t = (1, 2, "foo")
|
||||
items_s = {b"a", b"b", b"c"}
|
||||
|
||||
assert process_items(items_t, items_s) == (items_t, items_s)
|
||||
17
tests/test_tutorial/test_python_types/test_tutorial008.py
Normal file
17
tests/test_tutorial/test_python_types/test_tutorial008.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
from docs_src.python_types.tutorial008_py39 import process_items
|
||||
|
||||
|
||||
def test_process_items():
|
||||
with patch("builtins.print") as mock_print:
|
||||
process_items({"a": 1.0, "b": 2.5})
|
||||
|
||||
assert mock_print.call_count == 4
|
||||
call_args = [arg.args for arg in mock_print.call_args_list]
|
||||
assert call_args == [
|
||||
("a",),
|
||||
(1.0,),
|
||||
("b",),
|
||||
(2.5,),
|
||||
]
|
||||
27
tests/test_tutorial/test_python_types/test_tutorial008b.py
Normal file
27
tests/test_tutorial/test_python_types/test_tutorial008b.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import importlib
|
||||
from types import ModuleType
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="module",
|
||||
params=[
|
||||
pytest.param("tutorial008b_py39"),
|
||||
pytest.param("tutorial008b_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_module(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.python_types.{request.param}")
|
||||
return mod
|
||||
|
||||
|
||||
def test_process_items(module: ModuleType):
|
||||
with patch("builtins.print") as mock_print:
|
||||
module.process_item("a")
|
||||
|
||||
assert mock_print.call_count == 1
|
||||
mock_print.assert_called_with("a")
|
||||
@@ -0,0 +1,33 @@
|
||||
import importlib
|
||||
from types import ModuleType
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="module",
|
||||
params=[
|
||||
pytest.param("tutorial009_py39"),
|
||||
pytest.param("tutorial009_py310", marks=needs_py310),
|
||||
pytest.param("tutorial009b_py39"),
|
||||
],
|
||||
)
|
||||
def get_module(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.python_types.{request.param}")
|
||||
return mod
|
||||
|
||||
|
||||
def test_say_hi(module: ModuleType):
|
||||
with patch("builtins.print") as mock_print:
|
||||
module.say_hi("FastAPI")
|
||||
module.say_hi()
|
||||
|
||||
assert mock_print.call_count == 2
|
||||
call_args = [arg.args for arg in mock_print.call_args_list]
|
||||
assert call_args == [
|
||||
("Hey FastAPI!",),
|
||||
("Hello World",),
|
||||
]
|
||||
33
tests/test_tutorial/test_python_types/test_tutorial009c.py
Normal file
33
tests/test_tutorial/test_python_types/test_tutorial009c.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import importlib
|
||||
import re
|
||||
from types import ModuleType
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="module",
|
||||
params=[
|
||||
pytest.param("tutorial009c_py39"),
|
||||
pytest.param("tutorial009c_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_module(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.python_types.{request.param}")
|
||||
return mod
|
||||
|
||||
|
||||
def test_say_hi(module: ModuleType):
|
||||
with patch("builtins.print") as mock_print:
|
||||
module.say_hi("FastAPI")
|
||||
|
||||
mock_print.assert_called_once_with("Hey FastAPI!")
|
||||
|
||||
with pytest.raises(
|
||||
TypeError,
|
||||
match=re.escape("say_hi() missing 1 required positional argument: 'name'"),
|
||||
):
|
||||
module.say_hi()
|
||||
@@ -0,0 +1,5 @@
|
||||
from docs_src.python_types.tutorial010_py39 import Person, get_person_name
|
||||
|
||||
|
||||
def test_get_person_name():
|
||||
assert get_person_name(Person("John Doe")) == "John Doe"
|
||||
25
tests/test_tutorial/test_python_types/test_tutorial011.py
Normal file
25
tests/test_tutorial/test_python_types/test_tutorial011.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import runpy
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"module_name",
|
||||
[
|
||||
pytest.param("tutorial011_py39"),
|
||||
pytest.param("tutorial011_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def test_run_module(module_name: str):
|
||||
with patch("builtins.print") as mock_print:
|
||||
runpy.run_module(f"docs_src.python_types.{module_name}", run_name="__main__")
|
||||
|
||||
assert mock_print.call_count == 2
|
||||
call_args = [str(arg.args[0]) for arg in mock_print.call_args_list]
|
||||
assert call_args == [
|
||||
"id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]",
|
||||
"123",
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
from docs_src.python_types.tutorial012_py39 import User
|
||||
|
||||
|
||||
def test_user():
|
||||
user = User(name="John Doe", age=30)
|
||||
assert user.name == "John Doe"
|
||||
assert user.age == 30
|
||||
@@ -0,0 +1,5 @@
|
||||
from docs_src.python_types.tutorial013_py39 import say_hello
|
||||
|
||||
|
||||
def test_say_hello():
|
||||
assert say_hello("FastAPI") == "Hello FastAPI"
|
||||
126
tests/test_tutorial/test_query_params/test_tutorial001.py
Normal file
126
tests/test_tutorial/test_query_params/test_tutorial001.py
Normal file
@@ -0,0 +1,126 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial001_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.query_params.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("path", "expected_json"),
|
||||
[
|
||||
(
|
||||
"/items/",
|
||||
[{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}],
|
||||
),
|
||||
(
|
||||
"/items/?skip=1",
|
||||
[{"item_name": "Bar"}, {"item_name": "Baz"}],
|
||||
),
|
||||
(
|
||||
"/items/?skip=1&limit=1",
|
||||
[{"item_name": "Bar"}],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_read_user_item(client: TestClient, path, expected_json):
|
||||
response = client.get(path)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == expected_json
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"summary": "Read Item",
|
||||
"operationId": "read_item_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"title": "Skip",
|
||||
"type": "integer",
|
||||
"default": 0,
|
||||
},
|
||||
"name": "skip",
|
||||
"in": "query",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"title": "Limit",
|
||||
"type": "integer",
|
||||
"default": 10,
|
||||
},
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
127
tests/test_tutorial/test_query_params/test_tutorial002.py
Normal file
127
tests/test_tutorial/test_query_params/test_tutorial002.py
Normal file
@@ -0,0 +1,127 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.query_params.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("path", "expected_json"),
|
||||
[
|
||||
(
|
||||
"/items/foo",
|
||||
{"item_id": "foo"},
|
||||
),
|
||||
(
|
||||
"/items/bar?q=somequery",
|
||||
{"item_id": "bar", "q": "somequery"},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_read_user_item(client: TestClient, path, expected_json):
|
||||
response = client.get(path)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == expected_json
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"get": {
|
||||
"summary": "Read Item",
|
||||
"operationId": "read_item_items__item_id__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {"title": "Item Id", "type": "string"},
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"title": "Q",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
148
tests/test_tutorial/test_query_params/test_tutorial003.py
Normal file
148
tests/test_tutorial/test_query_params/test_tutorial003.py
Normal file
@@ -0,0 +1,148 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial003_py39"),
|
||||
pytest.param("tutorial003_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.query_params.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("path", "expected_json"),
|
||||
[
|
||||
(
|
||||
"/items/foo",
|
||||
{
|
||||
"item_id": "foo",
|
||||
"description": "This is an amazing item that has a long description",
|
||||
},
|
||||
),
|
||||
(
|
||||
"/items/bar?q=somequery",
|
||||
{
|
||||
"item_id": "bar",
|
||||
"q": "somequery",
|
||||
"description": "This is an amazing item that has a long description",
|
||||
},
|
||||
),
|
||||
(
|
||||
"/items/baz?short=true",
|
||||
{"item_id": "baz"},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_read_user_item(client: TestClient, path, expected_json):
|
||||
response = client.get(path)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == expected_json
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"get": {
|
||||
"summary": "Read Item",
|
||||
"operationId": "read_item_items__item_id__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {"title": "Item Id", "type": "string"},
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"title": "Q",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"title": "Short",
|
||||
"type": "boolean",
|
||||
"default": False,
|
||||
},
|
||||
"name": "short",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
156
tests/test_tutorial/test_query_params/test_tutorial004.py
Normal file
156
tests/test_tutorial/test_query_params/test_tutorial004.py
Normal file
@@ -0,0 +1,156 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial004_py39"),
|
||||
pytest.param("tutorial004_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.query_params.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("path", "expected_json"),
|
||||
[
|
||||
(
|
||||
"/users/123/items/foo",
|
||||
{
|
||||
"item_id": "foo",
|
||||
"owner_id": 123,
|
||||
"description": "This is an amazing item that has a long description",
|
||||
},
|
||||
),
|
||||
(
|
||||
"/users/1/items/bar?q=somequery",
|
||||
{
|
||||
"item_id": "bar",
|
||||
"owner_id": 1,
|
||||
"q": "somequery",
|
||||
"description": "This is an amazing item that has a long description",
|
||||
},
|
||||
),
|
||||
(
|
||||
"/users/42/items/baz?short=true",
|
||||
{"item_id": "baz", "owner_id": 42},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_read_user_item(client: TestClient, path, expected_json):
|
||||
response = client.get(path)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == expected_json
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/users/{user_id}/items/{item_id}": {
|
||||
"get": {
|
||||
"summary": "Read User Item",
|
||||
"operationId": "read_user_item_users__user_id__items__item_id__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {"title": "User Id", "type": "integer"},
|
||||
"name": "user_id",
|
||||
"in": "path",
|
||||
},
|
||||
{
|
||||
"required": True,
|
||||
"schema": {"title": "Item Id", "type": "string"},
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"title": "Q",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
},
|
||||
],
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"title": "Short",
|
||||
"type": "boolean",
|
||||
"default": False,
|
||||
},
|
||||
"name": "short",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "Validation Error",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial001_py39"),
|
||||
pytest.param("tutorial001_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.query_params_str_validations.{request.param}"
|
||||
)
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_query_params_str_validations_no_query(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_empty_str(client: TestClient):
|
||||
response = client.get("/items/", params={"q": ""})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_query(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "query"})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
"q": "query",
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"type": "string"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
pytest.param("tutorial002_an_py39"),
|
||||
pytest.param("tutorial002_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.query_params_str_validations.{request.param}"
|
||||
)
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_query_params_str_validations_no_query(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_empty_str(client: TestClient):
|
||||
response = client.get("/items/", params={"q": ""})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_query(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "query"})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
"q": "query",
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_too_long(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "q" * 51})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_too_long",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "String should have at most 50 characters",
|
||||
"input": "q" * 51,
|
||||
"ctx": {"max_length": 50},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"maxLength": 50,
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial003_py39"),
|
||||
pytest.param("tutorial003_py310", marks=needs_py310),
|
||||
pytest.param("tutorial003_an_py39"),
|
||||
pytest.param("tutorial003_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.query_params_str_validations.{request.param}"
|
||||
)
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_query_params_str_validations_no_query(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_query(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "query"})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
"q": "query",
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_too_short(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "qu"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_too_short",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "String should have at least 3 characters",
|
||||
"input": "qu",
|
||||
"ctx": {"min_length": 3},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_too_long(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "q" * 51})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_too_long",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "String should have at most 50 characters",
|
||||
"input": "q" * 51,
|
||||
"ctx": {"max_length": 50},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 50,
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial004_py39"),
|
||||
pytest.param("tutorial004_py310", marks=needs_py310),
|
||||
pytest.param("tutorial004_an_py39"),
|
||||
pytest.param("tutorial004_an_py310", marks=needs_py310),
|
||||
pytest.param(
|
||||
"tutorial004_regex_an_py310",
|
||||
marks=(
|
||||
needs_py310,
|
||||
pytest.mark.filterwarnings(
|
||||
"ignore:`regex` has been deprecated, please use `pattern` instead:DeprecationWarning"
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.query_params_str_validations.{request.param}"
|
||||
)
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_query_params_str_validations_no_query(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_fixedquery(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "fixedquery"})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
"q": "fixedquery",
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_nonregexquery(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "nonregexquery"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "String should match pattern '^fixedquery$'",
|
||||
"input": "nonregexquery",
|
||||
"ctx": {"pattern": "^fixedquery$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 50,
|
||||
"pattern": "^fixedquery$",
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial005_py39"),
|
||||
pytest.param("tutorial005_an_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.query_params_str_validations.{request.param}"
|
||||
)
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_query_params_str_validations_no_query(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
"q": "fixedquery",
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_query(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "query"})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
"q": "query",
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_short(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "fa"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_too_short",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "String should have at least 3 characters",
|
||||
"input": "fa",
|
||||
"ctx": {"min_length": 3},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"default": "fixedquery",
|
||||
"minLength": 3,
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial006_py39"),
|
||||
pytest.param("tutorial006_an_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.query_params_str_validations.{request.param}"
|
||||
)
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_query_params_str_validations_no_query(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_fixedquery(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "fixedquery"})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
"q": "fixedquery",
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_fixedquery_too_short(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "fa"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_too_short",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "String should have at least 3 characters",
|
||||
"input": "fa",
|
||||
"ctx": {"min_length": 3},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial006c_py39"),
|
||||
pytest.param("tutorial006c_py310", marks=needs_py310),
|
||||
pytest.param("tutorial006c_an_py39"),
|
||||
pytest.param("tutorial006c_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.query_params_str_validations.{request.param}"
|
||||
)
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
@pytest.mark.xfail(
|
||||
reason="Code example is not valid. See https://github.com/fastapi/fastapi/issues/12419"
|
||||
)
|
||||
def test_query_params_str_validations_no_query(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == { # pragma: no cover
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.xfail(
|
||||
reason="Code example is not valid. See https://github.com/fastapi/fastapi/issues/12419"
|
||||
)
|
||||
def test_query_params_str_validations_empty_str(client: TestClient):
|
||||
response = client.get("/items/?q=")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == { # pragma: no cover
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_query(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "query"})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
"q": "query",
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_short(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "fa"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_too_short",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "String should have at least 3 characters",
|
||||
"input": "fa",
|
||||
"ctx": {"min_length": 3},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"type": "string", "minLength": 3},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial007_py39"),
|
||||
pytest.param("tutorial007_py310", marks=needs_py310),
|
||||
pytest.param("tutorial007_an_py39"),
|
||||
pytest.param("tutorial007_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.query_params_str_validations.{request.param}"
|
||||
)
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_query_params_str_validations_no_query(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_fixedquery(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "fixedquery"})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
"q": "fixedquery",
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_fixedquery_too_short(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "fa"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_too_short",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "String should have at least 3 characters",
|
||||
"input": "fa",
|
||||
"ctx": {"min_length": 3},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Query string",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial008_py39"),
|
||||
pytest.param("tutorial008_py310", marks=needs_py310),
|
||||
pytest.param("tutorial008_an_py39"),
|
||||
pytest.param("tutorial008_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.query_params_str_validations.{request.param}"
|
||||
)
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_query_params_str_validations_no_query(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_fixedquery(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "fixedquery"})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
"q": "fixedquery",
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_fixedquery_too_short(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "fa"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_too_short",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "String should have at least 3 characters",
|
||||
"input": "fa",
|
||||
"ctx": {"min_length": 3},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Query string for the items to search in the database that have a good match",
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Query string",
|
||||
"description": "Query string for the items to search in the database that have a good match",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial009_py39"),
|
||||
pytest.param("tutorial009_py310", marks=needs_py310),
|
||||
pytest.param("tutorial009_an_py39"),
|
||||
pytest.param("tutorial009_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(
|
||||
f"docs_src.query_params_str_validations.{request.param}"
|
||||
)
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_query_params_str_validations_no_query(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
||||
|
||||
|
||||
def test_query_params_str_validations_item_query_fixedquery(client: TestClient):
|
||||
response = client.get("/items/", params={"item-query": "fixedquery"})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
|
||||
"q": "fixedquery",
|
||||
}
|
||||
|
||||
|
||||
def test_query_params_str_validations_q_fixedquery(client: TestClient):
|
||||
response = client.get("/items/", params={"q": "fixedquery"})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"type": "string"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Item-Query",
|
||||
},
|
||||
"required": False,
|
||||
"name": "item-query",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.response_directly.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_path_operation(client: TestClient):
|
||||
expected_content = """<?xml version="1.0"?>
|
||||
<shampoo>
|
||||
<Header>
|
||||
Apply shampoo here.
|
||||
</Header>
|
||||
<Body>
|
||||
You'll have to use soap here.
|
||||
</Body>
|
||||
</shampoo>
|
||||
"""
|
||||
|
||||
response = client.get("/legacy/")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.headers["content-type"] == "application/xml"
|
||||
assert response.text == expected_content
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0",
|
||||
},
|
||||
"openapi": "3.1.0",
|
||||
"paths": {
|
||||
"/legacy/": {
|
||||
"get": {
|
||||
"operationId": "get_legacy_data_legacy__get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {},
|
||||
},
|
||||
},
|
||||
"description": "Successful Response",
|
||||
},
|
||||
},
|
||||
"summary": "Get Legacy Data",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial001_py39"),
|
||||
pytest.param("tutorial001_py310", marks=needs_py310),
|
||||
pytest.param("tutorial001_01_py39"),
|
||||
pytest.param("tutorial001_01_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.response_model.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_read_items(client: TestClient):
|
||||
response = client.get("/items/")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == [
|
||||
{
|
||||
"name": "Portal Gun",
|
||||
"description": None,
|
||||
"price": 42.0,
|
||||
"tags": [],
|
||||
"tax": None,
|
||||
},
|
||||
{
|
||||
"name": "Plumbus",
|
||||
"description": None,
|
||||
"price": 32.0,
|
||||
"tags": [],
|
||||
"tax": None,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def test_create_item(client: TestClient):
|
||||
item_data = {
|
||||
"name": "Test Item",
|
||||
"description": "A test item",
|
||||
"price": 10.5,
|
||||
"tax": 1.5,
|
||||
"tags": ["test", "item"],
|
||||
}
|
||||
response = client.post("/items/", json=item_data)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == item_data
|
||||
|
||||
|
||||
def test_create_item_only_required(client: TestClient):
|
||||
response = client.post(
|
||||
"/items/",
|
||||
json={
|
||||
"name": "Test Item",
|
||||
"price": 10.5,
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"name": "Test Item",
|
||||
"price": 10.5,
|
||||
"description": None,
|
||||
"tax": None,
|
||||
"tags": [],
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/Item"},
|
||||
"title": "Response Read Items Items Get",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__get",
|
||||
},
|
||||
"post": {
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"},
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Create Item",
|
||||
"operationId": "create_item_items__post",
|
||||
},
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": ["name", "price"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
129
tests/test_tutorial/test_response_model/test_tutorial002.py
Normal file
129
tests/test_tutorial/test_response_model/test_tutorial002.py
Normal file
@@ -0,0 +1,129 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.response_model.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_post_user(client: TestClient):
|
||||
user_data = {
|
||||
"username": "foo",
|
||||
"password": "fighter",
|
||||
"email": "foo@example.com",
|
||||
"full_name": "Grave Dohl",
|
||||
}
|
||||
response = client.post(
|
||||
"/user/",
|
||||
json=user_data,
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == user_data
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/user/": {
|
||||
"post": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/UserIn"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Create User",
|
||||
"operationId": "create_user_user__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/UserIn"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"UserIn": {
|
||||
"title": "UserIn",
|
||||
"required": ["username", "password", "email"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
"password": {"title": "Password", "type": "string"},
|
||||
"email": {
|
||||
"title": "Email",
|
||||
"type": "string",
|
||||
"format": "email",
|
||||
},
|
||||
"full_name": {
|
||||
"title": "Full Name",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial001_py39"),
|
||||
pytest.param("tutorial002_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.response_status_code.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_create_item(client: TestClient):
|
||||
response = client.post("/items/", params={"name": "Test Item"})
|
||||
assert response.status_code == 201, response.text
|
||||
assert response.json() == {"name": "Test Item"}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"post": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "name",
|
||||
"in": "query",
|
||||
"required": True,
|
||||
"schema": {"title": "Name", "type": "string"},
|
||||
}
|
||||
],
|
||||
"summary": "Create Item",
|
||||
"operationId": "create_item_items__post",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.schema_extra_example.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_post_body_example(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"description": "A very nice Item",
|
||||
"price": 35.4,
|
||||
"tax": 3.2,
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
# insert_assert(response.json())
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"put": {
|
||||
"summary": "Update Item",
|
||||
"operationId": "update_item_items__item_id__put",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
"required": True,
|
||||
"schema": {"type": "integer", "title": "Item Id"},
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": True,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
"type": "array",
|
||||
"title": "Detail",
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"title": "HTTPValidationError",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"title": "Name",
|
||||
"examples": ["Foo"],
|
||||
},
|
||||
"description": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Description",
|
||||
"examples": ["A very nice Item"],
|
||||
},
|
||||
"price": {
|
||||
"type": "number",
|
||||
"title": "Price",
|
||||
"examples": [35.4],
|
||||
},
|
||||
"tax": {
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
"title": "Tax",
|
||||
"examples": [3.2],
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["name", "price"],
|
||||
"title": "Item",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Location",
|
||||
},
|
||||
"msg": {"type": "string", "title": "Message"},
|
||||
"type": {"type": "string", "title": "Error Type"},
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"title": "ValidationError",
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial003_py39"),
|
||||
pytest.param("tutorial003_py310", marks=needs_py310),
|
||||
pytest.param("tutorial003_an_py39"),
|
||||
pytest.param("tutorial003_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.schema_extra_example.{request.param}")
|
||||
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_post_body_example(client: TestClient):
|
||||
response = client.put(
|
||||
"/items/5",
|
||||
json={
|
||||
"name": "Foo",
|
||||
"description": "A very nice Item",
|
||||
"price": 35.4,
|
||||
"tax": 3.2,
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
# insert_assert(response.json())
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/{item_id}": {
|
||||
"put": {
|
||||
"summary": "Update Item",
|
||||
"operationId": "update_item_items__item_id__put",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
"required": True,
|
||||
"schema": {"type": "integer", "title": "Item Id"},
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": True,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
"examples": [
|
||||
{
|
||||
"description": "A very nice Item",
|
||||
"name": "Foo",
|
||||
"price": 35.4,
|
||||
"tax": 3.2,
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
"type": "array",
|
||||
"title": "Detail",
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"title": "HTTPValidationError",
|
||||
},
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {"type": "string", "title": "Name"},
|
||||
"description": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Description",
|
||||
},
|
||||
"price": {"type": "number", "title": "Price"},
|
||||
"tax": {
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
"title": "Tax",
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["name", "price"],
|
||||
"title": "Item",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Location",
|
||||
},
|
||||
"msg": {"type": "string", "title": "Message"},
|
||||
"type": {"type": "string", "title": "Error Type"},
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"title": "ValidationError",
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
71
tests/test_tutorial/test_security/test_tutorial002.py
Normal file
71
tests/test_tutorial/test_security/test_tutorial002.py
Normal file
@@ -0,0 +1,71 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial002_py39"),
|
||||
pytest.param("tutorial002_py310", marks=needs_py310),
|
||||
pytest.param("tutorial002_an_py39"),
|
||||
pytest.param("tutorial002_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.security.{request.param}")
|
||||
client = TestClient(mod.app)
|
||||
return client
|
||||
|
||||
|
||||
def test_no_token(client: TestClient):
|
||||
response = client.get("/users/me")
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.json() == {"detail": "Not authenticated"}
|
||||
assert response.headers["WWW-Authenticate"] == "Bearer"
|
||||
|
||||
|
||||
def test_token(client: TestClient):
|
||||
response = client.get("/users/me", headers={"Authorization": "Bearer testtoken"})
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"username": "testtokenfakedecoded",
|
||||
"email": "john@example.com",
|
||||
"full_name": "John Doe",
|
||||
"disabled": None,
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/users/me": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
"summary": "Read Users Me",
|
||||
"operationId": "read_users_me_users_me_get",
|
||||
"security": [{"OAuth2PasswordBearer": []}],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"securitySchemes": {
|
||||
"OAuth2PasswordBearer": {
|
||||
"type": "oauth2",
|
||||
"flows": {"password": {"scopes": {}, "tokenUrl": "token"}},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
363
tests/test_tutorial/test_security/test_tutorial004.py
Normal file
363
tests/test_tutorial/test_security/test_tutorial004.py
Normal file
@@ -0,0 +1,363 @@
|
||||
import importlib
|
||||
from types import ModuleType
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="mod",
|
||||
params=[
|
||||
pytest.param("tutorial004_py39"),
|
||||
pytest.param("tutorial004_py310", marks=needs_py310),
|
||||
pytest.param("tutorial004_an_py39"),
|
||||
pytest.param("tutorial004_an_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_mod(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.security.{request.param}")
|
||||
|
||||
return mod
|
||||
|
||||
|
||||
def get_access_token(*, username="johndoe", password="secret", client: TestClient):
|
||||
data = {"username": username, "password": password}
|
||||
response = client.post("/token", data=data)
|
||||
content = response.json()
|
||||
access_token = content.get("access_token")
|
||||
return access_token
|
||||
|
||||
|
||||
def test_login(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
response = client.post("/token", data={"username": "johndoe", "password": "secret"})
|
||||
assert response.status_code == 200, response.text
|
||||
content = response.json()
|
||||
assert "access_token" in content
|
||||
assert content["token_type"] == "bearer"
|
||||
|
||||
|
||||
def test_login_incorrect_password(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
response = client.post(
|
||||
"/token", data={"username": "johndoe", "password": "incorrect"}
|
||||
)
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.json() == {"detail": "Incorrect username or password"}
|
||||
|
||||
|
||||
def test_login_incorrect_username(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
response = client.post("/token", data={"username": "foo", "password": "secret"})
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.json() == {"detail": "Incorrect username or password"}
|
||||
|
||||
|
||||
def test_no_token(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
response = client.get("/users/me")
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.json() == {"detail": "Not authenticated"}
|
||||
assert response.headers["WWW-Authenticate"] == "Bearer"
|
||||
|
||||
|
||||
def test_token(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
access_token = get_access_token(client=client)
|
||||
response = client.get(
|
||||
"/users/me", headers={"Authorization": f"Bearer {access_token}"}
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"username": "johndoe",
|
||||
"full_name": "John Doe",
|
||||
"email": "johndoe@example.com",
|
||||
"disabled": False,
|
||||
}
|
||||
|
||||
|
||||
def test_incorrect_token(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
response = client.get("/users/me", headers={"Authorization": "Bearer nonexistent"})
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.json() == {"detail": "Could not validate credentials"}
|
||||
assert response.headers["WWW-Authenticate"] == "Bearer"
|
||||
|
||||
|
||||
def test_incorrect_token_type(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
response = client.get(
|
||||
"/users/me", headers={"Authorization": "Notexistent testtoken"}
|
||||
)
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.json() == {"detail": "Not authenticated"}
|
||||
assert response.headers["WWW-Authenticate"] == "Bearer"
|
||||
|
||||
|
||||
def test_verify_password(mod: ModuleType):
|
||||
assert mod.verify_password(
|
||||
"secret", mod.fake_users_db["johndoe"]["hashed_password"]
|
||||
)
|
||||
|
||||
|
||||
def test_get_password_hash(mod: ModuleType):
|
||||
assert mod.get_password_hash("johndoe")
|
||||
|
||||
|
||||
def test_create_access_token(mod: ModuleType):
|
||||
access_token = mod.create_access_token(data={"data": "foo"})
|
||||
assert access_token
|
||||
|
||||
|
||||
def test_token_no_sub(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
|
||||
response = client.get(
|
||||
"/users/me",
|
||||
headers={
|
||||
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoiZm9vIn0.9ynBhuYb4e6aW3oJr_K_TBgwcMTDpRToQIE25L57rOE"
|
||||
},
|
||||
)
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.json() == {"detail": "Could not validate credentials"}
|
||||
assert response.headers["WWW-Authenticate"] == "Bearer"
|
||||
|
||||
|
||||
def test_token_no_username(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
|
||||
response = client.get(
|
||||
"/users/me",
|
||||
headers={
|
||||
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmb28ifQ.NnExK_dlNAYyzACrXtXDrcWOgGY2JuPbI4eDaHdfK5Y"
|
||||
},
|
||||
)
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.json() == {"detail": "Could not validate credentials"}
|
||||
assert response.headers["WWW-Authenticate"] == "Bearer"
|
||||
|
||||
|
||||
def test_token_nonexistent_user(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
|
||||
response = client.get(
|
||||
"/users/me",
|
||||
headers={
|
||||
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VybmFtZTpib2IifQ.HcfCW67Uda-0gz54ZWTqmtgJnZeNem0Q757eTa9EZuw"
|
||||
},
|
||||
)
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.json() == {"detail": "Could not validate credentials"}
|
||||
assert response.headers["WWW-Authenticate"] == "Bearer"
|
||||
|
||||
|
||||
def test_token_inactive_user(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
alice_user_data = {
|
||||
"username": "alice",
|
||||
"full_name": "Alice Wonderson",
|
||||
"email": "alice@example.com",
|
||||
"hashed_password": mod.get_password_hash("secretalice"),
|
||||
"disabled": True,
|
||||
}
|
||||
with patch.dict(f"{mod.__name__}.fake_users_db", {"alice": alice_user_data}):
|
||||
access_token = get_access_token(
|
||||
username="alice", password="secretalice", client=client
|
||||
)
|
||||
response = client.get(
|
||||
"/users/me", headers={"Authorization": f"Bearer {access_token}"}
|
||||
)
|
||||
assert response.status_code == 400, response.text
|
||||
assert response.json() == {"detail": "Inactive user"}
|
||||
|
||||
|
||||
def test_read_items(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
access_token = get_access_token(client=client)
|
||||
response = client.get(
|
||||
"/users/me/items/", headers={"Authorization": f"Bearer {access_token}"}
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == [{"item_id": "Foo", "owner": "johndoe"}]
|
||||
|
||||
|
||||
def test_openapi_schema(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/token": {
|
||||
"post": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Token"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Login For Access Token",
|
||||
"operationId": "login_for_access_token_token_post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_login_for_access_token_token_post"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
},
|
||||
}
|
||||
},
|
||||
"/users/me/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/User"}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
"summary": "Read Users Me",
|
||||
"operationId": "read_users_me_users_me__get",
|
||||
"security": [{"OAuth2PasswordBearer": []}],
|
||||
}
|
||||
},
|
||||
"/users/me/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
"summary": "Read Own Items",
|
||||
"operationId": "read_own_items_users_me_items__get",
|
||||
"security": [{"OAuth2PasswordBearer": []}],
|
||||
}
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"User": {
|
||||
"title": "User",
|
||||
"required": ["username"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
"email": {
|
||||
"title": "Email",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"full_name": {
|
||||
"title": "Full Name",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"disabled": {
|
||||
"title": "Disabled",
|
||||
"anyOf": [{"type": "boolean"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"Token": {
|
||||
"title": "Token",
|
||||
"required": ["access_token", "token_type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"access_token": {"title": "Access Token", "type": "string"},
|
||||
"token_type": {"title": "Token Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"Body_login_for_access_token_token_post": {
|
||||
"title": "Body_login_for_access_token_token_post",
|
||||
"required": ["username", "password"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"grant_type": {
|
||||
"title": "Grant Type",
|
||||
"anyOf": [
|
||||
{"pattern": "^password$", "type": "string"},
|
||||
{"type": "null"},
|
||||
],
|
||||
},
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
"password": {
|
||||
"title": "Password",
|
||||
"type": "string",
|
||||
"format": "password",
|
||||
},
|
||||
"scope": {"title": "Scope", "type": "string", "default": ""},
|
||||
"client_id": {
|
||||
"title": "Client Id",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"client_secret": {
|
||||
"title": "Client Secret",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"format": "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"securitySchemes": {
|
||||
"OAuth2PasswordBearer": {
|
||||
"type": "oauth2",
|
||||
"flows": {
|
||||
"password": {
|
||||
"scopes": {},
|
||||
"tokenUrl": "token",
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
89
tests/test_tutorial/test_security/test_tutorial007.py
Normal file
89
tests/test_tutorial/test_security/test_tutorial007.py
Normal file
@@ -0,0 +1,89 @@
|
||||
import importlib
|
||||
from base64 import b64encode
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="client",
|
||||
params=[
|
||||
pytest.param("tutorial007_py39"),
|
||||
pytest.param("tutorial007_an_py39"),
|
||||
],
|
||||
)
|
||||
def get_client(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.security.{request.param}")
|
||||
return TestClient(mod.app)
|
||||
|
||||
|
||||
def test_security_http_basic(client: TestClient):
|
||||
response = client.get("/users/me", auth=("stanleyjobson", "swordfish"))
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"username": "stanleyjobson"}
|
||||
|
||||
|
||||
def test_security_http_basic_no_credentials(client: TestClient):
|
||||
response = client.get("/users/me")
|
||||
assert response.json() == {"detail": "Not authenticated"}
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.headers["WWW-Authenticate"] == "Basic"
|
||||
|
||||
|
||||
def test_security_http_basic_invalid_credentials(client: TestClient):
|
||||
response = client.get(
|
||||
"/users/me", headers={"Authorization": "Basic notabase64token"}
|
||||
)
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.headers["WWW-Authenticate"] == "Basic"
|
||||
assert response.json() == {"detail": "Not authenticated"}
|
||||
|
||||
|
||||
def test_security_http_basic_non_basic_credentials(client: TestClient):
|
||||
payload = b64encode(b"johnsecret").decode("ascii")
|
||||
auth_header = f"Basic {payload}"
|
||||
response = client.get("/users/me", headers={"Authorization": auth_header})
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.headers["WWW-Authenticate"] == "Basic"
|
||||
assert response.json() == {"detail": "Not authenticated"}
|
||||
|
||||
|
||||
def test_security_http_basic_invalid_username(client: TestClient):
|
||||
response = client.get("/users/me", auth=("alice", "swordfish"))
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.json() == {"detail": "Incorrect username or password"}
|
||||
assert response.headers["WWW-Authenticate"] == "Basic"
|
||||
|
||||
|
||||
def test_security_http_basic_invalid_password(client: TestClient):
|
||||
response = client.get("/users/me", auth=("stanleyjobson", "wrongpassword"))
|
||||
assert response.status_code == 401, response.text
|
||||
assert response.json() == {"detail": "Incorrect username or password"}
|
||||
assert response.headers["WWW-Authenticate"] == "Basic"
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/users/me": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
"summary": "Read Current User",
|
||||
"operationId": "read_current_user_users_me_get",
|
||||
"security": [{"HTTPBasic": []}],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}}
|
||||
},
|
||||
}
|
||||
78
tests/test_tutorial/test_settings/test_app01.py
Normal file
78
tests/test_tutorial/test_settings/test_app01.py
Normal file
@@ -0,0 +1,78 @@
|
||||
import importlib
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsAnyStr
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import ValidationError
|
||||
from pytest import MonkeyPatch
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="mod_name",
|
||||
params=[
|
||||
pytest.param("app01_py39"),
|
||||
],
|
||||
)
|
||||
def get_mod_name(request: pytest.FixtureRequest):
|
||||
return f"docs_src.settings.{request.param}.main"
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_test_client(mod_name: str, monkeypatch: MonkeyPatch) -> TestClient:
|
||||
if mod_name in sys.modules:
|
||||
del sys.modules[mod_name]
|
||||
monkeypatch.setenv("ADMIN_EMAIL", "admin@example.com")
|
||||
main_mod = importlib.import_module(mod_name)
|
||||
return TestClient(main_mod.app)
|
||||
|
||||
|
||||
def test_settings_validation_error(mod_name: str, monkeypatch: MonkeyPatch):
|
||||
monkeypatch.delenv("ADMIN_EMAIL", raising=False)
|
||||
if mod_name in sys.modules:
|
||||
del sys.modules[mod_name] # pragma: no cover
|
||||
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
importlib.import_module(mod_name)
|
||||
assert exc_info.value.errors() == [
|
||||
{
|
||||
"loc": ("admin_email",),
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
"input": {},
|
||||
"url": IsAnyStr,
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def test_app(client: TestClient):
|
||||
response = client.get("/info")
|
||||
data = response.json()
|
||||
assert data == {
|
||||
"app_name": "Awesome API",
|
||||
"admin_email": "admin@example.com",
|
||||
"items_per_user": 50,
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/info": {
|
||||
"get": {
|
||||
"operationId": "info_info_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
"summary": "Info",
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
0
tests/test_tutorial/test_static_files/__init__.py
Normal file
0
tests/test_tutorial/test_static_files/__init__.py
Normal file
40
tests/test_tutorial/test_static_files/test_tutorial001.py
Normal file
40
tests/test_tutorial/test_static_files/test_tutorial001.py
Normal file
@@ -0,0 +1,40 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def client():
|
||||
static_dir: Path = Path(os.getcwd()) / "static"
|
||||
static_dir.mkdir(exist_ok=True)
|
||||
sample_file = static_dir / "sample.txt"
|
||||
sample_file.write_text("This is a sample static file.")
|
||||
from docs_src.static_files.tutorial001_py39 import app
|
||||
|
||||
with TestClient(app) as client:
|
||||
yield client
|
||||
sample_file.unlink()
|
||||
static_dir.rmdir()
|
||||
|
||||
|
||||
def test_static_files(client: TestClient):
|
||||
response = client.get("/static/sample.txt")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.text == "This is a sample static file."
|
||||
|
||||
|
||||
def test_static_files_not_found(client: TestClient):
|
||||
response = client.get("/static/non_existent_file.txt")
|
||||
assert response.status_code == 404, response.text
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {},
|
||||
}
|
||||
Reference in New Issue
Block a user