"
+ ),
+ "status": 405,
+ "title": (
+ "Operation delete not found for "
+ "http://petstore.swagger.io/v1/pets/12"
+ ),
+ }
+ ]
+ }
+ assert response.status_code == 405
+ assert response.json() == expected_data
+
+ def test_get_valid(self, client):
+ headers = {
+ "Authorization": "Basic testuser",
+ }
+ response = client.get("/v1/pets/12", headers=headers)
+
+ expected_data = {
+ "data": {
+ "id": 12,
+ "name": "Cat",
+ "ears": {
+ "healthy": True,
+ },
+ },
+ }
+ assert response.status_code == 200
+ assert response.json() == expected_data
+
+
+class TestPetPhotoEndpoint(BaseTestPetstore):
+ def test_get_valid(self, client, data_gif):
+ client.cookies.set("user", "1")
+ headers = {
+ "Authorization": "Basic testuser",
+ "Api-Key": self.api_key_encoded,
+ }
+
+ response = client.get(
+ "/v1/pets/1/photo",
+ headers=headers,
+ )
+
+ assert response.content == data_gif
+ assert response.status_code == 200
+
+ def test_post_valid(self, client, data_gif):
+ client.cookies.set("user", "1")
+ content_type = "image/gif"
+ headers = {
+ "Authorization": "Basic testuser",
+ "Api-Key": self.api_key_encoded,
+ "Content-Type": content_type,
+ }
+
+ response = client.post(
+ "/v1/pets/1/photo",
+ headers=headers,
+ content=data_gif,
+ )
+
+ assert not response.text
+ assert response.status_code == 201
diff --git a/tests/integration/contrib/starlette/test_starlette_project.py b/tests/integration/contrib/starlette/test_starlette_project.py
index fc799a30..d1e8ed54 100644
--- a/tests/integration/contrib/starlette/test_starlette_project.py
+++ b/tests/integration/contrib/starlette/test_starlette_project.py
@@ -183,7 +183,7 @@ def test_post_media_type_invalid(self, client):
"title": (
"Content for the following mimetype not found: "
"text/html. "
- "Valid mimetypes: ['application/json', 'application/x-www-form-urlencoded', 'text/plain']"
+ "Valid mimetypes: ['application/json', 'application/x-www-form-urlencoded', 'multipart/form-data', 'text/plain']"
),
}
]
diff --git a/tests/integration/data/v3.0/parent-reference/openapi.yaml b/tests/integration/data/v3.0/parent-reference/openapi.yaml
new file mode 100644
index 00000000..51150416
--- /dev/null
+++ b/tests/integration/data/v3.0/parent-reference/openapi.yaml
@@ -0,0 +1,7 @@
+openapi: "3.0.0"
+info:
+ title: sample
+ version: "0.1"
+paths:
+ /books:
+ $ref: "./paths/books.yaml"
\ No newline at end of file
diff --git a/tests/integration/data/v3.0/parent-reference/paths/books.yaml b/tests/integration/data/v3.0/parent-reference/paths/books.yaml
new file mode 100644
index 00000000..d625f4f5
--- /dev/null
+++ b/tests/integration/data/v3.0/parent-reference/paths/books.yaml
@@ -0,0 +1,10 @@
+get:
+ responses:
+ "200":
+ description: OK
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: "../schemas/book.yaml#/Book"
\ No newline at end of file
diff --git a/tests/integration/data/v3.0/parent-reference/schemas/book.yaml b/tests/integration/data/v3.0/parent-reference/schemas/book.yaml
new file mode 100644
index 00000000..1bf35402
--- /dev/null
+++ b/tests/integration/data/v3.0/parent-reference/schemas/book.yaml
@@ -0,0 +1,9 @@
+Book:
+ type: object
+ properties:
+ id:
+ $ref: "#/BookId"
+ title:
+ type: string
+BookId:
+ type: string
\ No newline at end of file
diff --git a/tests/integration/data/v3.0/petstore.yaml b/tests/integration/data/v3.0/petstore.yaml
index d26816ac..735fd96c 100644
--- a/tests/integration/data/v3.0/petstore.yaml
+++ b/tests/integration/data/v3.0/petstore.yaml
@@ -150,6 +150,9 @@ paths:
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/PetCreate'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PetWithPhotoCreate'
text/plain: {}
responses:
'201':
@@ -375,6 +378,16 @@ components:
oneOf:
- $ref: "#/components/schemas/Cat"
- $ref: "#/components/schemas/Bird"
+ PetWithPhotoCreate:
+ type: object
+ x-model: PetWithPhotoCreate
+ allOf:
+ - $ref: "#/components/schemas/PetCreatePartOne"
+ - $ref: "#/components/schemas/PetCreatePartTwo"
+ - $ref: "#/components/schemas/PetCreatePartPhoto"
+ oneOf:
+ - $ref: "#/components/schemas/Cat"
+ - $ref: "#/components/schemas/Bird"
PetCreatePartOne:
type: object
x-model: PetCreatePartOne
@@ -395,6 +408,15 @@ components:
$ref: "#/components/schemas/Position"
healthy:
type: boolean
+ PetCreatePartPhoto:
+ type: object
+ x-model: PetCreatePartPhoto
+ properties:
+ photo:
+ $ref: "#/components/schemas/PetPhoto"
+ PetPhoto:
+ type: string
+ format: binary
Bird:
type: object
x-model: Bird
diff --git a/tests/integration/test_petstore.py b/tests/integration/test_petstore.py
index f00bbfbc..58fbb760 100644
--- a/tests/integration/test_petstore.py
+++ b/tests/integration/test_petstore.py
@@ -100,11 +100,15 @@ def test_get_pets(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- result = unmarshal_request(
- request,
- spec=spec,
- cls=V30RequestParametersUnmarshaller,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ result = unmarshal_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersUnmarshaller,
+ )
assert result.parameters == Parameters(
query={
@@ -159,11 +163,15 @@ def test_get_pets_response(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- result = unmarshal_request(
- request,
- spec=spec,
- cls=V30RequestParametersUnmarshaller,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ result = unmarshal_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersUnmarshaller,
+ )
assert result.parameters == Parameters(
query={
@@ -219,11 +227,15 @@ def test_get_pets_response_media_type(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- result = unmarshal_request(
- request,
- spec=spec,
- cls=V30RequestParametersUnmarshaller,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ result = unmarshal_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersUnmarshaller,
+ )
assert result.parameters == Parameters(
query={
@@ -267,11 +279,15 @@ def test_get_pets_invalid_response(self, spec, response_unmarshaller):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- result = unmarshal_request(
- request,
- spec=spec,
- cls=V30RequestParametersUnmarshaller,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ result = unmarshal_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersUnmarshaller,
+ )
assert result.parameters == Parameters(
query={
@@ -339,11 +355,15 @@ def test_get_pets_ids_param(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- result = unmarshal_request(
- request,
- spec=spec,
- cls=V30RequestParametersUnmarshaller,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ result = unmarshal_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersUnmarshaller,
+ )
assert result.parameters == Parameters(
query={
@@ -391,11 +411,15 @@ def test_get_pets_tags_param(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- result = unmarshal_request(
- request,
- spec=spec,
- cls=V30RequestParametersUnmarshaller,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ result = unmarshal_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersUnmarshaller,
+ )
assert result.parameters == Parameters(
query={
@@ -443,12 +467,16 @@ def test_get_pets_parameter_schema_error(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- with pytest.raises(ParameterValidationError) as exc_info:
- validate_request(
- request,
- spec=spec,
- cls=V30RequestParametersUnmarshaller,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ with pytest.raises(ParameterValidationError) as exc_info:
+ validate_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersUnmarshaller,
+ )
assert type(exc_info.value.__cause__) is InvalidSchemaValue
result = unmarshal_request(
@@ -475,12 +503,16 @@ def test_get_pets_wrong_parameter_type(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- with pytest.raises(ParameterValidationError) as exc_info:
- validate_request(
- request,
- spec=spec,
- cls=V30RequestParametersValidator,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ with pytest.raises(ParameterValidationError) as exc_info:
+ validate_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersValidator,
+ )
assert type(exc_info.value.__cause__) is CastError
result = unmarshal_request(
@@ -502,12 +534,16 @@ def test_get_pets_raises_missing_required_param(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- with pytest.raises(MissingRequiredParameter):
- validate_request(
- request,
- spec=spec,
- cls=V30RequestParametersValidator,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ with pytest.raises(MissingRequiredParameter):
+ validate_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersValidator,
+ )
result = unmarshal_request(
request, spec=spec, cls=V30RequestBodyUnmarshaller
@@ -534,12 +570,16 @@ def test_get_pets_empty_value(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- with pytest.raises(ParameterValidationError) as exc_info:
- validate_request(
- request,
- spec=spec,
- cls=V30RequestParametersValidator,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ with pytest.raises(ParameterValidationError) as exc_info:
+ validate_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersValidator,
+ )
assert type(exc_info.value.__cause__) is EmptyQueryParameterValue
result = unmarshal_request(
@@ -567,11 +607,15 @@ def test_get_pets_allow_empty_value(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- result = unmarshal_request(
- request,
- spec=spec,
- cls=V30RequestParametersUnmarshaller,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ result = unmarshal_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersUnmarshaller,
+ )
assert result.parameters == Parameters(
query={
@@ -605,11 +649,15 @@ def test_get_pets_none_value(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- result = unmarshal_request(
- request,
- spec=spec,
- cls=V30RequestParametersUnmarshaller,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ result = unmarshal_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersUnmarshaller,
+ )
assert result.parameters == Parameters(
query={
@@ -644,11 +692,15 @@ def test_get_pets_param_order(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- result = unmarshal_request(
- request,
- spec=spec,
- cls=V30RequestParametersUnmarshaller,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ result = unmarshal_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersUnmarshaller,
+ )
assert result.parameters == Parameters(
query={
@@ -688,11 +740,15 @@ def test_get_pets_param_coordinates(self, spec):
with pytest.warns(
DeprecationWarning, match="limit parameter is deprecated"
):
- result = unmarshal_request(
- request,
- spec=spec,
- cls=V30RequestParametersUnmarshaller,
- )
+ with pytest.warns(
+ DeprecationWarning,
+ match="Use of allowEmptyValue property is deprecated",
+ ):
+ result = unmarshal_request(
+ request,
+ spec=spec,
+ cls=V30RequestParametersUnmarshaller,
+ )
assert is_dataclass(result.parameters.query["coordinates"])
assert (
diff --git a/tests/integration/unmarshalling/test_request_unmarshaller.py b/tests/integration/unmarshalling/test_request_unmarshaller.py
index 2993275b..0eefa3f0 100644
--- a/tests/integration/unmarshalling/test_request_unmarshaller.py
+++ b/tests/integration/unmarshalling/test_request_unmarshaller.py
@@ -201,6 +201,7 @@ def test_invalid_content_type(self, request_unmarshaller):
availableMimetypes=[
"application/json",
"application/x-www-form-urlencoded",
+ "multipart/form-data",
"text/plain",
],
)
diff --git a/tests/integration/unmarshalling/test_unmarshallers.py b/tests/integration/unmarshalling/test_unmarshallers.py
index 764fc3af..54e944a3 100644
--- a/tests/integration/unmarshalling/test_unmarshallers.py
+++ b/tests/integration/unmarshalling/test_unmarshallers.py
@@ -1840,6 +1840,25 @@ def test_object_property_nullable(self, unmarshallers_factory):
assert result == value
+ def test_subschema_nullable(self, unmarshallers_factory):
+ schema = {
+ "oneOf": [
+ {
+ "type": "integer",
+ },
+ {
+ "nullable": True,
+ },
+ ]
+ }
+ spec = SchemaPath.from_dict(schema)
+ unmarshaller = unmarshallers_factory.create(spec)
+ value = None
+
+ result = unmarshaller.unmarshal(value)
+
+ assert result is None
+
class TestOAS30RequestSchemaUnmarshallersFactory(
BaseTestOASSchemaUnmarshallersFactoryCall,
@@ -2086,3 +2105,22 @@ def test_any_null(self, unmarshallers_factory):
result = unmarshaller.unmarshal(None)
assert result is None
+
+ def test_subschema_null(self, unmarshallers_factory):
+ schema = {
+ "oneOf": [
+ {
+ "type": "integer",
+ },
+ {
+ "type": "null",
+ },
+ ]
+ }
+ spec = SchemaPath.from_dict(schema)
+ unmarshaller = unmarshallers_factory.create(spec)
+ value = None
+
+ result = unmarshaller.unmarshal(value)
+
+ assert result is None
diff --git a/tests/integration/validation/test_parent_reference.py b/tests/integration/validation/test_parent_reference.py
new file mode 100644
index 00000000..21e37351
--- /dev/null
+++ b/tests/integration/validation/test_parent_reference.py
@@ -0,0 +1,45 @@
+import json
+
+import pytest
+from jsonschema_path import SchemaPath
+
+from openapi_core import Config
+from openapi_core import OpenAPI
+from openapi_core import V30ResponseUnmarshaller
+from openapi_core.testing import MockRequest
+from openapi_core.testing import MockResponse
+
+
+class TestParentReference:
+
+ spec_path = "data/v3.0/parent-reference/openapi.yaml"
+
+ @pytest.fixture
+ def unmarshaller(self, content_factory):
+ content, base_uri = content_factory.from_file(self.spec_path)
+ return V30ResponseUnmarshaller(
+ spec=SchemaPath.from_dict(content, base_uri=base_uri)
+ )
+
+ @pytest.fixture
+ def openapi(self, content_factory):
+ content, base_uri = content_factory.from_file(self.spec_path)
+ spec = SchemaPath.from_dict(content, base_uri=base_uri)
+ config = Config(spec_base_uri=base_uri)
+ return OpenAPI(spec, config=config)
+
+ def test_valid(self, openapi):
+ request = MockRequest(host_url="", method="GET", path="/books")
+ response = MockResponse(
+ data=json.dumps([{"id": "BOOK:01", "title": "Test Book"}]).encode()
+ )
+
+ openapi.validate_response(request, response)
+
+ def test_unmarshal(self, unmarshaller):
+ request = MockRequest(host_url="", method="GET", path="/books")
+ response = MockResponse(
+ data=json.dumps([{"id": "BOOK:01", "title": "Test Book"}]).encode()
+ )
+
+ unmarshaller.unmarshal(request, response)
diff --git a/tests/integration/validation/test_request_validators.py b/tests/integration/validation/test_request_validators.py
index 14a7e6d6..eaac8dbf 100644
--- a/tests/integration/validation/test_request_validators.py
+++ b/tests/integration/validation/test_request_validators.py
@@ -106,6 +106,7 @@ def test_media_type_not_found(self, request_validator):
availableMimetypes=[
"application/json",
"application/x-www-form-urlencoded",
+ "multipart/form-data",
"text/plain",
],
)
diff --git a/tests/unit/templating/test_media_types_finders.py b/tests/unit/templating/test_media_types_finders.py
index c94ff5b6..d83cc1f1 100644
--- a/tests/unit/templating/test_media_types_finders.py
+++ b/tests/unit/templating/test_media_types_finders.py
@@ -21,10 +21,19 @@ def content(self, spec):
def finder(self, content):
return MediaTypeFinder(content)
- def test_charset(self, finder, content):
- mimetype = "text/html; charset=utf-8"
-
- mimetype, parameters, _ = finder.find(mimetype)
+ @pytest.mark.parametrize(
+ "media_type",
+ [
+ # equivalent according to RFC 9110
+ "text/html;charset=utf-8",
+ 'Text/HTML;Charset="utf-8"',
+ 'text/html; charset="utf-8"',
+ "text/html;charset=UTF-8",
+ "text/html ; charset=utf-8",
+ ],
+ )
+ def test_charset(self, finder, content, media_type):
+ mimetype, parameters, _ = finder.find(media_type)
assert mimetype == "text/*"
assert parameters == {"charset": "utf-8"}
diff --git a/tests/unit/templating/test_templating_util.py b/tests/unit/templating/test_templating_util.py
index b268e4f0..815f6cb0 100644
--- a/tests/unit/templating/test_templating_util.py
+++ b/tests/unit/templating/test_templating_util.py
@@ -29,6 +29,7 @@ def test_exact(self):
[
("/{test_id}/test", {"test_id": "test"}),
("/{test.id}/test", {"test.id": "test"}),
+ ("/{test-id}/test", {"test-id": "test"}),
],
)
def test_chars_valid(self, path_pattern, expected):
@@ -49,7 +50,6 @@ def test_chars_valid(self, path_pattern, expected):
"path_pattern,expected",
[
("/{test~id}/test", {"test~id": "test"}),
- ("/{test-id}/test", {"test-id": "test"}),
],
)
def test_special_chars_valid(self, path_pattern, expected):
diff --git a/tests/unit/test_shortcuts.py b/tests/unit/test_shortcuts.py
index 0dd18651..9a3f36c9 100644
--- a/tests/unit/test_shortcuts.py
+++ b/tests/unit/test_shortcuts.py
@@ -423,8 +423,7 @@ def test_request_response_error(self, mock_unmarshal, spec_v31):
mock_unmarshal.return_value = ResultMock(error_to_raise=ValueError)
with pytest.raises(ValueError):
- with pytest.warns(DeprecationWarning):
- unmarshal_response(request, response, spec=spec_v31)
+ unmarshal_response(request, response, spec=spec_v31)
mock_unmarshal.assert_called_once_with(request, response)
@@ -597,15 +596,13 @@ def test_spec_invalid(self, spec_invalid):
request = mock.Mock(spec=Request)
with pytest.raises(SpecError):
- with pytest.warns(DeprecationWarning):
- validate_request(request, spec=spec_invalid)
+ validate_request(request, spec=spec_invalid)
def test_spec_not_detected(self, spec_v20):
request = mock.Mock(spec=Request)
with pytest.raises(SpecError):
- with pytest.warns(DeprecationWarning):
- validate_request(request, spec=spec_v20)
+ validate_request(request, spec=spec_v20)
def test_request_type_invalid(self, spec_v31):
request = mock.sentinel.request
@@ -733,8 +730,7 @@ def test_webhook_request_validator_not_found(self, spec_v30):
request = mock.Mock(spec=WebhookRequest)
with pytest.raises(SpecError):
- with pytest.warns(DeprecationWarning):
- validate_request(request, spec=spec_v30)
+ validate_request(request, spec=spec_v30)
@mock.patch(
"openapi_core.validation.request.validators.V31WebhookRequestValidator."
@@ -889,16 +885,14 @@ def test_spec_not_detected(self, spec_invalid):
response = mock.Mock(spec=Response)
with pytest.raises(SpecError):
- with pytest.warns(DeprecationWarning):
- validate_response(request, response, spec=spec_invalid)
+ validate_response(request, response, spec=spec_invalid)
def test_spec_not_supported(self, spec_v20):
request = mock.Mock(spec=Request)
response = mock.Mock(spec=Response)
with pytest.raises(SpecError):
- with pytest.warns(DeprecationWarning):
- validate_response(request, response, spec=spec_v20)
+ validate_response(request, response, spec=spec_v20)
def test_request_type_invalid(self, spec_v31):
request = mock.sentinel.request
@@ -965,8 +959,7 @@ def test_webhook_response_validator_not_found(self, spec_v30):
response = mock.Mock(spec=Response)
with pytest.raises(SpecError):
- with pytest.warns(DeprecationWarning):
- validate_response(request, response, spec=spec_v30)
+ validate_response(request, response, spec=spec_v30)
@mock.patch(
"openapi_core.validation.response.validators.V31WebhookResponseValidator."
diff --git a/tests/unit/unmarshalling/test_request_unmarshallers.py b/tests/unit/unmarshalling/test_request_unmarshallers.py
new file mode 100644
index 00000000..a407d567
--- /dev/null
+++ b/tests/unit/unmarshalling/test_request_unmarshallers.py
@@ -0,0 +1,136 @@
+import enum
+
+import pytest
+from jsonschema_path import SchemaPath
+
+from openapi_core import V30RequestUnmarshaller
+from openapi_core import V31RequestUnmarshaller
+from openapi_core.datatypes import Parameters
+from openapi_core.testing import MockRequest
+
+
+class Colors(enum.Enum):
+
+ YELLOW = "yellow"
+ BLUE = "blue"
+ RED = "red"
+
+ @classmethod
+ def of(cls, v: str):
+ for it in cls:
+ if it.value == v:
+ return it
+ raise ValueError(f"Invalid value: {v}")
+
+
+class TestRequestUnmarshaller:
+
+ @pytest.fixture(scope="session")
+ def spec_dict(self):
+ return {
+ "openapi": "3.1.0",
+ "info": {
+ "title": "Test request body unmarshaller",
+ "version": "0.1",
+ },
+ "paths": {
+ "/resources": {
+ "post": {
+ "description": "POST resources test request",
+ "requestBody": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/createResource"
+ }
+ }
+ },
+ },
+ "responses": {
+ "201": {"description": "Resource was created."}
+ },
+ },
+ "get": {
+ "description": "POST resources test request",
+ "parameters": [
+ {
+ "name": "color",
+ "in": "query",
+ "required": False,
+ "schema": {
+ "$ref": "#/components/schemas/colors"
+ },
+ },
+ ],
+ "responses": {
+ "default": {
+ "description": "Returned resources matching request."
+ }
+ },
+ },
+ }
+ },
+ "components": {
+ "schemas": {
+ "colors": {
+ "type": "string",
+ "enum": ["yellow", "blue", "red"],
+ "format": "enum_Colors",
+ },
+ "createResource": {
+ "type": "object",
+ "properties": {
+ "resId": {"type": "integer"},
+ "color": {"$ref": "#/components/schemas/colors"},
+ },
+ "required": ["resId", "color"],
+ },
+ }
+ },
+ }
+
+ @pytest.fixture(scope="session")
+ def spec(self, spec_dict):
+ return SchemaPath.from_dict(spec_dict)
+
+ @pytest.mark.parametrize(
+ "req_unmarshaller_cls",
+ [V30RequestUnmarshaller, V31RequestUnmarshaller],
+ )
+ def test_request_body_extra_unmarshaller(self, spec, req_unmarshaller_cls):
+ ru = req_unmarshaller_cls(
+ spec=spec, extra_format_unmarshallers={"enum_Colors": Colors.of}
+ )
+ request = MockRequest(
+ host_url="http://example.com",
+ method="post",
+ path="/resources",
+ data=b'{"resId": 23498572, "color": "blue"}',
+ )
+ result = ru.unmarshal(request)
+
+ assert not result.errors
+ assert result.body == {"resId": 23498572, "color": Colors.BLUE}
+ assert result.parameters == Parameters()
+
+ @pytest.mark.parametrize(
+ "req_unmarshaller_cls",
+ [V30RequestUnmarshaller, V31RequestUnmarshaller],
+ )
+ def test_request_param_extra_unmarshaller(
+ self, spec, req_unmarshaller_cls
+ ):
+ ru = req_unmarshaller_cls(
+ spec=spec, extra_format_unmarshallers={"enum_Colors": Colors.of}
+ )
+ request = MockRequest(
+ host_url="http://example.com",
+ method="get",
+ path="/resources",
+ args={"color": "blue"},
+ )
+ result = ru.unmarshal(request)
+
+ assert not result.errors
+ assert result.parameters == Parameters(query=dict(color=Colors.BLUE))
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy