Files
connexion/tests/conftest.py
Leonardo Festa fc003ca140 Removed internal variable pass_context_arg_name (#1568)
* Removed internal variable pass_context_arg_name

* fixed issue with personalized context name in tests

* restored code from pr suggestion

* restore decorator functionality

now the function accept a pass_context_arg boolean parameter,
instead of the pass_context_arg_name value

* Fixed security test checks, now passes tests

* Removed pass_context_arg, fixed security handler

fixed security handler as suggested
removed pass_context_arg as before

* Fix context injection test

Co-authored-by: Niels Dewulf <87133686+nielsbox@users.noreply.github.com>
Co-authored-by: Robbe Sneyders <robbe.sneyders@ml6.eu>
2022-09-22 22:53:25 +02:00

285 lines
8.0 KiB
Python

import json
import logging
import pathlib
import pytest
from connexion import App
from connexion.resolver import MethodResolver, MethodViewResolver
from connexion.security import SecurityHandlerFactory
from werkzeug.test import Client, EnvironBuilder
logging.basicConfig(level=logging.INFO)
TEST_FOLDER = pathlib.Path(__file__).parent
FIXTURES_FOLDER = TEST_FOLDER / "fixtures"
SPEC_FOLDER = TEST_FOLDER / "fakeapi"
OPENAPI2_SPEC = ["swagger.yaml"]
OPENAPI3_SPEC = ["openapi.yaml"]
SPECS = OPENAPI2_SPEC + OPENAPI3_SPEC
METHOD_VIEW_RESOLVERS = [MethodResolver, MethodViewResolver]
class FakeResponse:
def __init__(self, status_code, text):
"""
:type status_code: int
:type text: ste
"""
self.status_code = status_code
self.text = text
self.ok = status_code == 200
def json(self):
return json.loads(self.text)
def fixed_get_environ():
"""See https://github.com/pallets/werkzeug/issues/2347"""
original_get_environ = EnvironBuilder.get_environ
def f(self):
result = original_get_environ(self)
result.pop("HTTP_CONTENT_TYPE", None)
result.pop("HTTP_CONTENT_LENGTH", None)
return result
return f
EnvironBuilder.get_environ = fixed_get_environ()
def buffered_open():
"""For use with ASGI middleware"""
original_open = Client.open
def f(*args, **kwargs):
kwargs["buffered"] = True
return original_open(*args, **kwargs)
return f
Client.open = buffered_open()
# Helper fixtures functions
# =========================
@pytest.fixture
def oauth_requests(monkeypatch):
class FakeClient:
@staticmethod
async def get(url, params=None, headers=None, timeout=None):
"""
:type url: str
:type params: dict| None
"""
headers = headers or {}
if url == "https://oauth.example/token_info":
token = headers.get("Authorization", "invalid").split()[-1]
if token in ["100", "has_myscope"]:
return FakeResponse(
200, '{"uid": "test-user", "scope": ["myscope"]}'
)
if token in ["200", "has_wrongscope"]:
return FakeResponse(
200, '{"uid": "test-user", "scope": ["wrongscope"]}'
)
if token == "has_myscope_otherscope":
return FakeResponse(
200, '{"uid": "test-user", "scope": ["myscope", "otherscope"]}'
)
if token in ["300", "is_not_invalid"]:
return FakeResponse(404, "")
if token == "has_scopes_in_scopes_with_s":
return FakeResponse(
200, '{"uid": "test-user", "scopes": ["myscope", "otherscope"]}'
)
return url
monkeypatch.setattr(SecurityHandlerFactory, "client", FakeClient())
@pytest.fixture
def security_handler_factory():
security_handler_factory = SecurityHandlerFactory()
yield security_handler_factory
@pytest.fixture
def app():
cnx_app = App(__name__, port=5001, specification_dir=SPEC_FOLDER, debug=True)
cnx_app.add_api("api.yaml", validate_responses=True)
return cnx_app
@pytest.fixture
def simple_api_spec_dir():
return FIXTURES_FOLDER / "simple"
@pytest.fixture
def problem_api_spec_dir():
return FIXTURES_FOLDER / "problem"
@pytest.fixture
def secure_api_spec_dir():
return FIXTURES_FOLDER / "secure_api"
@pytest.fixture
def default_param_error_spec_dir():
return FIXTURES_FOLDER / "default_param_error"
@pytest.fixture
def json_validation_spec_dir():
return FIXTURES_FOLDER / "json_validation"
@pytest.fixture(scope="session")
def json_datetime_dir():
return FIXTURES_FOLDER / "datetime_support"
def build_app_from_fixture(
api_spec_folder, spec_file="openapi.yaml", middlewares=None, **kwargs
):
debug = True
if "debug" in kwargs:
debug = kwargs["debug"]
del kwargs["debug"]
cnx_app = App(
__name__,
port=5001,
specification_dir=FIXTURES_FOLDER / api_spec_folder,
middlewares=middlewares,
debug=debug,
)
cnx_app.add_api(spec_file, **kwargs)
cnx_app._spec_file = spec_file
return cnx_app
@pytest.fixture(scope="session", params=SPECS)
def simple_app(request):
return build_app_from_fixture("simple", request.param, validate_responses=True)
@pytest.fixture(scope="session", params=OPENAPI3_SPEC)
def simple_openapi_app(request):
return build_app_from_fixture("simple", request.param, validate_responses=True)
@pytest.fixture(scope="session", params=SPECS)
def reverse_proxied_app(request):
# adapted from http://flask.pocoo.org/snippets/35/
class ReverseProxied:
def __init__(self, app, script_name=None, scheme=None, server=None):
self.app = app
self.script_name = script_name
self.scheme = scheme
self.server = server
def __call__(self, environ, start_response):
script_name = environ.get("HTTP_X_FORWARDED_PATH", "") or self.script_name
if script_name:
environ["SCRIPT_NAME"] = "/" + script_name.lstrip("/")
path_info = environ["PATH_INFO"]
if path_info.startswith(script_name):
environ["PATH_INFO_OLD"] = path_info
environ["PATH_INFO"] = path_info[len(script_name) :]
scheme = environ.get("HTTP_X_SCHEME", "") or self.scheme
if scheme:
environ["wsgi.url_scheme"] = scheme
server = environ.get("HTTP_X_FORWARDED_SERVER", "") or self.server
if server:
environ["HTTP_HOST"] = server
return self.app(environ, start_response)
app = build_app_from_fixture("simple", request.param, validate_responses=True)
flask_app = app.app
proxied = ReverseProxied(flask_app.wsgi_app, script_name="/reverse_proxied/")
flask_app.wsgi_app = proxied
return app
@pytest.fixture(scope="session", params=SPECS)
def snake_case_app(request):
return build_app_from_fixture(
"snake_case", request.param, validate_responses=True, pythonic_params=True
)
@pytest.fixture(scope="session", params=SPECS)
def invalid_resp_allowed_app(request):
return build_app_from_fixture("simple", request.param, validate_responses=False)
@pytest.fixture(scope="session", params=SPECS)
def strict_app(request):
return build_app_from_fixture(
"simple", request.param, validate_responses=True, strict_validation=True
)
@pytest.fixture(scope="session", params=SPECS)
def problem_app(request):
return build_app_from_fixture("problem", request.param, validate_responses=True)
@pytest.fixture(scope="session", params=SPECS)
def schema_app(request):
return build_app_from_fixture(
"different_schemas", request.param, validate_responses=True
)
@pytest.fixture(scope="session", params=SPECS)
def secure_endpoint_app(request):
return build_app_from_fixture(
"secure_endpoint",
request.param,
validate_responses=True,
)
@pytest.fixture(scope="session", params=SPECS)
def secure_api_app(request):
options = {"swagger_ui": False}
return build_app_from_fixture(
"secure_api", request.param, options=options, auth_all_paths=True
)
@pytest.fixture(scope="session", params=SPECS)
def unordered_definition_app(request):
return build_app_from_fixture("unordered_definition", request.param)
@pytest.fixture(scope="session", params=SPECS)
def bad_operations_app(request):
return build_app_from_fixture("bad_operations", request.param, resolver_error=501)
@pytest.fixture(scope="session", params=SPECS)
def method_view_app(request):
return build_app_from_fixture(
"method_view",
request.param,
resolver=MethodViewResolver("fakeapi.example_method_view"),
)
@pytest.fixture(scope="session", params=METHOD_VIEW_RESOLVERS)
def method_view_resolver(request):
return request.param