# Path: oauthenticator/tests/mocks.py
# class MockAsyncHTTPClient(SimpleAsyncHTTPClient):
#     """A mock AsyncHTTPClient that allows registering handlers for mocked requests
# 
#     Call .add_host to mock requests made to a given host.
# 
#     """
# 
#     def initialize(self, *args, **kwargs):
#         super().initialize(*args, **kwargs)
#         self.hosts = {}
# 
#     def add_host(self, host, paths):
#         """Add a host whose requests should be mocked.
# 
#         Args:
#             host (str): the host to mock (e.g. 'api.github.com')
#             paths (list(str|regex, callable)): a list of paths (or regexps for paths)
#                 and callables to be called for those paths.
#                 The mock handlers will receive the request as their only argument.
# 
#         Mock handlers can return:
#             - None
#             - int (empty response with this status code)
#             - str, bytes for raw response content (status=200)
#             - list, dict for JSON response (status=200)
#             - HTTPResponse (passed unmodified)
# 
#         Example::
# 
#             client.add_host('api.github.com', [
#                 ('/user': lambda request: {'login': 'name'})
#             ])
#         """
#         self.hosts[host] = paths
# 
#     def fetch_impl(self, request, response_callback):
#         urlinfo = urlparse(request.url)
#         host = urlinfo.hostname
#         if host not in self.hosts:
#             app_log.warning("Not mocking request to %s", request.url)
#             return super().fetch_impl(request, response_callback)
#         paths = self.hosts[host]
#         response = None
#         for path_spec, handler in paths:
#             if isinstance(path_spec, str):
#                 if path_spec == urlinfo.path:
#                     response = handler(request)
#                     break
#             else:
#                 if path_spec.match(urlinfo.path):
#                     response = handler(request)
#                     break
# 
#         if response is None:
#             response = HTTPResponse(request=request, code=404, reason=request.url)
#         elif isinstance(response, int):
#             response = HTTPResponse(request=request, code=response)
#         elif isinstance(response, bytes):
#             response = HTTPResponse(
#                 request=request,
#                 code=200,
#                 buffer=BytesIO(response),
#             )
#         elif isinstance(response, str):
#             response = HTTPResponse(
#                 request=request,
#                 code=200,
#                 buffer=BytesIO(response.encode('utf8')),
#             )
#         elif isinstance(response, (dict, list)):
#             response = HTTPResponse(
#                 request=request,
#                 code=200,
#                 buffer=BytesIO(json.dumps(response).encode('utf8')),
#                 headers={'Content-Type': 'application/json'},
#             )
# 
#         response_callback(response)


import inspect
from pytest import fixture
from tornado.httpclient import AsyncHTTPClient
from tornado.platform.asyncio import AsyncIOMainLoop
from .mocks import MockAsyncHTTPClient




def pytest_collection_modifyitems(items):
    """add asyncio marker to all async tests"""
    for item in items:
        if inspect.iscoroutinefunction(item.obj):
            item.add_marker('asyncio')


@fixture
def io_loop(event_loop, request):
    """Same as pytest-tornado.io_loop, adapted for tornado 5"""
    io_loop = AsyncIOMainLoop()
    io_loop.make_current()
    assert io_loop.asyncio_loop is event_loop

    def _close():
        io_loop.clear_current()
        io_loop.close(all_fds=True)

    request.addfinalizer(_close)
    return io_loop


@fixture
def client(io_loop, request):
    """Return mocked AsyncHTTPClient"""
    before = AsyncHTTPClient.configured_class()

# Path: oauthenticator/tests/mocks.py
# class MockAsyncHTTPClient(SimpleAsyncHTTPClient):
#     """A mock AsyncHTTPClient that allows registering handlers for mocked requests
# 
#     Call .add_host to mock requests made to a given host.
# 
#     """
# 
#     def initialize(self, *args, **kwargs):
#         super().initialize(*args, **kwargs)
#         self.hosts = {}
# 
#     def add_host(self, host, paths):
#         """Add a host whose requests should be mocked.
# 
#         Args:
#             host (str): the host to mock (e.g. 'api.github.com')
#             paths (list(str|regex, callable)): a list of paths (or regexps for paths)
#                 and callables to be called for those paths.
#                 The mock handlers will receive the request as their only argument.
# 
#         Mock handlers can return:
#             - None
#             - int (empty response with this status code)
#             - str, bytes for raw response content (status=200)
#             - list, dict for JSON response (status=200)
#             - HTTPResponse (passed unmodified)
# 
#         Example::
# 
#             client.add_host('api.github.com', [
#                 ('/user': lambda request: {'login': 'name'})
#             ])
#         """
#         self.hosts[host] = paths
# 
#     def fetch_impl(self, request, response_callback):
#         urlinfo = urlparse(request.url)
#         host = urlinfo.hostname
#         if host not in self.hosts:
#             app_log.warning("Not mocking request to %s", request.url)
#             return super().fetch_impl(request, response_callback)
#         paths = self.hosts[host]
#         response = None
#         for path_spec, handler in paths:
#             if isinstance(path_spec, str):
#                 if path_spec == urlinfo.path:
#                     response = handler(request)
#                     break
#             else:
#                 if path_spec.match(urlinfo.path):
#                     response = handler(request)
#                     break
# 
#         if response is None:
#             response = HTTPResponse(request=request, code=404, reason=request.url)
#         elif isinstance(response, int):
#             response = HTTPResponse(request=request, code=response)
#         elif isinstance(response, bytes):
#             response = HTTPResponse(
#                 request=request,
#                 code=200,
#                 buffer=BytesIO(response),
#             )
#         elif isinstance(response, str):
#             response = HTTPResponse(
#                 request=request,
#                 code=200,
#                 buffer=BytesIO(response.encode('utf8')),
#             )
#         elif isinstance(response, (dict, list)):
#             response = HTTPResponse(
#                 request=request,
#                 code=200,
#                 buffer=BytesIO(json.dumps(response).encode('utf8')),
#                 headers={'Content-Type': 'application/json'},
#             )
# 
#         response_callback(response)


# Path: oauthenticator/tests/conftest.py
import inspect
from pytest import fixture
from tornado.httpclient import AsyncHTTPClient
from tornado.platform.asyncio import AsyncIOMainLoop
from .mocks import MockAsyncHTTPClient





def pytest_collection_modifyitems(items):
    """add asyncio marker to all async tests"""
    for item in items:
        if inspect.iscoroutinefunction(item.obj):
            item.add_marker('asyncio')


@fixture
def io_loop(event_loop, request):
    """Same as pytest-tornado.io_loop, adapted for tornado 5"""
    io_loop = AsyncIOMainLoop()
    io_loop.make_current()
    assert io_loop.asyncio_loop is event_loop

    def _close():
        io_loop.clear_current()
        io_loop.close(all_fds=True)

    request.addfinalizer(_close)
    return io_loop


@fixture
def client(io_loop, request):
    """Return mocked AsyncHTTPClient"""
    before = AsyncHTTPClient.configured_class()

    AsyncHTTPClient.configure(MockAsyncHTTPClient)