def test_loose_urlencoded_form_open_api_3(assert_parameters, make_openapi_3_schema, make_user_schema, user_jsonschema): # The schema doesn't define "type": "object" loose_schema = { "schema": make_user_schema(is_loose=True, middle_name={ "type": "string", "nullable": True }) } schema = make_openapi_3_schema({ "required": True, "content": { "application/x-www-form-urlencoded": loose_schema }, }) assert_parameters( schema, PayloadAlternatives([ OpenAPI30Body(definition=loose_schema, media_type="application/x-www-form-urlencoded", required=True) ]), # But when it is converted to JSON Schema, Schemathesis sets `type` to `object` # Therefore it corresponds to the default JSON Schema defined for a User [user_jsonschema], )
def test_invalid_body_in_get_disable_validation(simple_schema): schema = schemathesis.from_dict(simple_schema, validate_schema=False) endpoint = Endpoint( path="/foo", method="GET", definition=EndpointDefinition({}, {}, "foo", []), schema=schema, body=PayloadAlternatives( [ OpenAPI20Body( { "name": "attributes", "in": "body", "required": True, "schema": {"required": ["foo"], "type": "object", "properties": {"foo": {"type": "string"}}}, }, media_type="application/json", ) ] ), ) strategy = get_case_strategy(endpoint) @given(strategy) @settings(max_examples=1) def test(case): assert case.body is not None test()
def test_invalid_body_in_get(swagger_20): operation = APIOperation( path="/foo", method="GET", definition=OperationDefinition({}, {}, "foo", []), schema=swagger_20, body=PayloadAlternatives([ OpenAPI20Body( { "name": "attributes", "in": "body", "required": True, "schema": { "required": ["foo"], "type": "object", "properties": { "foo": { "type": "string" } } }, }, media_type="application/json", ) ]), ) with pytest.raises( InvalidSchema, match=r"^Body parameters are defined for GET request.$"): get_case_strategy(operation).example()
def test_empty_content(): # When the "content" value is empty in "requestBody" raw_schema = { "openapi": "3.0.2", "info": {"title": "Test", "description": "Test", "version": "0.1.0"}, "paths": {"/body": {"post": {"requestBody": {"content": {}}, "responses": {"200": {"description": "OK"}}}}}, } schema = schemathesis.from_dict(raw_schema) # Then the body processing should be no-op operation = schema["/body"]["POST"] assert operation.body == PayloadAlternatives([])
def test_resolving_multiple_files(): raw_schema = { "swagger": "2.0", "info": {"title": "Example API", "description": "An API to test Schemathesis", "version": "1.0.0"}, "host": "127.0.0.1:8888", "basePath": "/api", "schemes": ["http"], "produces": ["application/json"], "paths": { "/teapot": { "post": { "parameters": [ { "schema": {"$ref": "test/data/petstore_v2.yaml#/definitions/User"}, "in": "body", "name": "user", "required": True, } ], "responses": {"200": {"description": "OK"}}, } } }, } schema = schemathesis.from_dict(raw_schema) assert schema["/teapot"]["post"].body == PayloadAlternatives( [ OpenAPI20Body( { "schema": { "type": "object", "properties": { "id": {"type": "integer", "format": "int64"}, "username": {"type": "string"}, "firstName": {"type": "string"}, "lastName": {"type": "string"}, "email": {"type": "string"}, "password": {"type": "string"}, "phone": {"type": "string"}, "userStatus": {"type": "integer", "format": "int32", "description": "User Status"}, }, "xml": {"name": "User"}, }, "in": "body", "name": "user", "required": True, }, media_type="application/json", ) ] )
def test_default_strategies_bytes(swagger_20): endpoint = make_endpoint( swagger_20, body=PayloadAlternatives( [ OpenAPI20Body( {"in": "body", "name": "byte", "required": True, "schema": {"type": "string", "format": "byte"}}, media_type="text/plain", ) ] ), ) result = get_case_strategy(endpoint).example() assert isinstance(result.body, str) b64decode(result.body)
def test_default_strategies_binary(swagger_20): operation = make_operation( swagger_20, body=PayloadAlternatives([ OpenAPI20CompositeBody.from_parameters( { "name": "upfile", "in": "formData", "type": "file", "required": True, }, media_type="multipart/form-data", ) ]), ) result = get_case_strategy(operation).example() assert isinstance(result.body["upfile"], bytes)
def test_forms_open_api_2(consumes, assert_parameters, make_openapi_2_schema, user_jsonschema, open_api_2_user_form_parameters): # In Open API 2.0, forms are separate "formData" parameters schema = make_openapi_2_schema(consumes, open_api_2_user_form_parameters) assert_parameters( schema, PayloadAlternatives([ # They are represented as a single "composite" body for each media type OpenAPI20CompositeBody( definition=[ OpenAPI20Parameter(parameter) for parameter in open_api_2_user_form_parameters ], media_type=value, ) for value in consumes ]), # Each converted schema should correspond to the default User schema. [user_jsonschema] * len(consumes), )
def test_payload_open_api_2( consumes, assert_parameters, make_openapi_2_schema, open_api_2_user_form_with_file_parameters, open_api_2_user_in_body, user_jsonschema, ): # A single "body" parameter is used for all payload variants schema = make_openapi_2_schema(consumes, [open_api_2_user_in_body]) assert_parameters( schema, PayloadAlternatives([ OpenAPI20Body(definition=open_api_2_user_in_body, media_type=value) for value in consumes ]), # For each one the schema is extracted from the parameter definition and transformed to the proper JSON Schema [user_jsonschema] * len(consumes), )
def test_multipart_form_open_api_3(assert_parameters, make_openapi_3_schema, user_jsonschema_with_file, open_api_3_user_with_file): # A regular multipart for with a file upload in Open API 3 schema = make_openapi_3_schema({ "required": True, "content": { "multipart/form-data": { "schema": open_api_3_user_with_file } }, }) assert_parameters( schema, PayloadAlternatives([ OpenAPI30Body(definition={"schema": open_api_3_user_with_file}, media_type="multipart/form-data", required=True) ]), # When converted, the schema corresponds the default schema defined for a User object with a file [user_jsonschema_with_file], )
def test_urlencoded_form_open_api_3(assert_parameters, make_openapi_3_schema, open_api_3_user, user_jsonschema): # A regular urlencoded form in Open API 3 schema = make_openapi_3_schema({ "required": True, "content": { "application/x-www-form-urlencoded": { "schema": open_api_3_user } }, }) assert_parameters( schema, PayloadAlternatives([ OpenAPI30Body( definition={"schema": open_api_3_user}, media_type="application/x-www-form-urlencoded", required=True, ) ]), # It should correspond to the default User schema [user_jsonschema], )
def test_payload_open_api_3(media_types, assert_parameters, make_openapi_3_schema, open_api_3_user, user_jsonschema): schema = make_openapi_3_schema({ "required": True, "content": { media_type: { "schema": open_api_3_user } for media_type in media_types }, }) assert_parameters( schema, PayloadAlternatives([ OpenAPI30Body(definition={"schema": open_api_3_user}, media_type=media_type, required=True) for media_type in media_types ]), # The converted schema should correspond the schema in the relevant "requestBody" part # In this case they are the same [user_jsonschema] * len(media_types), )
def test_multipart_form_open_api_2( consumes, assert_parameters, make_openapi_2_schema, user_jsonschema_with_file, open_api_2_user_form_with_file_parameters, ): # Multipart forms are represented as a list of "formData" parameters schema = make_openapi_2_schema(consumes, open_api_2_user_form_with_file_parameters) assert_parameters( schema, PayloadAlternatives([ # Is represented with a "composite" body OpenAPI20CompositeBody( definition=[ OpenAPI20Parameter(parameter) for parameter in open_api_2_user_form_with_file_parameters ], media_type="multipart/form-data", ) ]), [user_jsonschema_with_file], )
def test_make_operation_body(body): # See GH-1069 # When `requestBody` is present in the link definition # And in the target operation operation = APIOperation( path="/users/", method="post", verbose_name="GET /users/{user_id}", definition=ANY, schema=ANY, base_url=ANY, body=PayloadAlternatives([body]), ) body = {"foo": "bar"} # Literal value link = Link( name="Link", operation=operation, parameters={}, request_body={"requestBody": body}, ) # Then it should be taken into account during creation a modified version of that operation new_operation = link.make_operation([ParsedData( {}, body=body)]) # Actual parsed data will contain the literal assert new_operation.body[0].definition["schema"] == {"enum": [body]}
def test_complex_dereference(testdir, complex_schema): schema = schemathesis.from_path(complex_schema) path = Path(str(testdir)) body = OpenAPI30Body( { "schema": { "additionalProperties": False, "description": "Test", "properties": { "profile": { "additionalProperties": False, "description": "Test", "properties": {"id": {"type": "integer"}}, "required": ["id"], "type": "object", }, "username": {"type": "string"}, }, "required": ["username", "profile"], "type": "object", } }, required=True, media_type="application/json", ) assert schema.endpoints["/teapot"]["POST"] == Endpoint( base_url="file:///", path="/teapot", method="post", definition=EndpointDefinition( { "requestBody": { "content": { "application/json": {"schema": {"$ref": "../schemas/teapot/create.yaml#/TeapotCreateRequest"}} }, "description": "Test.", "required": True, }, "responses": {"default": {"$ref": "../../common/responses.yaml#/DefaultError"}}, "summary": "Test", "tags": ["ancillaries"], }, { "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": False, "description": "Test", "properties": { "profile": { "additionalProperties": False, "description": "Test", "properties": {"id": {"type": "integer"}}, "required": ["id"], "type": "object", }, "username": {"type": "string"}, }, "required": ["username", "profile"], "type": "object", } } }, "description": "Test.", "required": True, }, "responses": { "default": { "content": { "application/json": { "schema": { "additionalProperties": False, "properties": { "key": {"anyOf": [{"type": "string"}, {"type": "null"}]}, "referenced": {"anyOf": [{"type": "string"}, {"type": "null"}]}, }, "required": ["key", "referenced"], "type": "object", } } }, "description": "Probably an error", } }, "summary": "Test", "tags": ["ancillaries"], }, scope=f"{path.as_uri()}/root/paths/teapot.yaml#/TeapotCreatePath", parameters=[body], ), body=PayloadAlternatives([body]), schema=schema, )