# Path: federation/exceptions.py
# class NoSuitableProtocolFoundError(Exception):
#     """No suitable protocol found to pass this payload message to."""
#     pass
# 
# Path: federation/inbound.py
# def handle_receive(
#         request: RequestType,
#         user: UserType = None,
#         sender_key_fetcher: Callable[[str], str] = None,
#         skip_author_verification: bool = False
# ) -> Tuple[str, str, List]:
#     """Takes a request and passes it to the correct protocol.
# 
#     Returns a tuple of:
#       - sender id
#       - protocol name
#       - list of entities
# 
#     NOTE! The returned sender is NOT necessarily the *author* of the entity. By sender here we're
#     talking about the sender of the *request*. If this object is being relayed by the sender, the author
#     could actually be a different identity.
# 
#     :arg request: Request object of type RequestType - note not a HTTP request even though the structure is similar
#     :arg user: User that will be passed to `protocol.receive` (only required on private encrypted content)
#         MUST have a `private_key` and `id` if given.
#     :arg sender_key_fetcher: Function that accepts sender handle and returns public key (optional)
#     :arg skip_author_verification: Don't verify sender (test purposes, false default)
#     :returns: Tuple of sender id, protocol name and list of entity objects
#     """
#     logger.debug("handle_receive: processing request: %s", request)
#     found_protocol = identify_protocol_by_request(request)
# 
#     logger.debug("handle_receive: using protocol %s", found_protocol.PROTOCOL_NAME)
#     protocol = found_protocol.Protocol()
#     sender, message = protocol.receive(
#         request, user, sender_key_fetcher, skip_author_verification=skip_author_verification)
#     logger.debug("handle_receive: sender %s, message %s", sender, message)
# 
#     mappers = importlib.import_module("federation.entities.%s.mappers" % found_protocol.PROTOCOL_NAME)
#     entities = mappers.message_to_objects(message, sender, sender_key_fetcher, user)
#     logger.debug("handle_receive: entities %s", entities)
# 
#     return sender, found_protocol.PROTOCOL_NAME, entities
# 
# Path: federation/types.py
# class RequestType:
#     """
#     Emulates structure of a Django HttpRequest for compatibility.
#     """
#     body: Union[str, bytes] = attr.ib()
# 
#     # Required when dealing with incoming AP payloads
#     headers: Dict = attr.ib(default=None)
#     method: str = attr.ib(default=None)
#     url: str = attr.ib(default=None)


from unittest.mock import patch
from federation.exceptions import NoSuitableProtocolFoundError
from federation.inbound import handle_receive
from federation.protocols.diaspora.protocol import Protocol
from federation.tests.fixtures.payloads import DIASPORA_PUBLIC_PAYLOAD
from federation.types import RequestType
import pytest




class TestHandleReceiveProtocolIdentification:
    def test_handle_receive_routes_to_identified_protocol(self):
        payload = RequestType(body=DIASPORA_PUBLIC_PAYLOAD)
        with patch.object(
                    Protocol,
                    'receive',
                    return_value=("foobar@domain.tld", "<foobar></foobar>")) as mock_receive,\
                patch(
                    "federation.entities.diaspora.mappers.message_to_objects",
                    return_value=[]) as mock_message_to_objects:
            handle_receive(payload)
            assert mock_receive.called

    def test_handle_receive_raises_on_unidentified_protocol(self):
        payload = RequestType(body="foobar")
        with pytest.raises(NoSuitableProtocolFoundError):

# Path: federation/exceptions.py
# class NoSuitableProtocolFoundError(Exception):
#     """No suitable protocol found to pass this payload message to."""
#     pass
# 
# Path: federation/inbound.py
# def handle_receive(
#         request: RequestType,
#         user: UserType = None,
#         sender_key_fetcher: Callable[[str], str] = None,
#         skip_author_verification: bool = False
# ) -> Tuple[str, str, List]:
#     """Takes a request and passes it to the correct protocol.
# 
#     Returns a tuple of:
#       - sender id
#       - protocol name
#       - list of entities
# 
#     NOTE! The returned sender is NOT necessarily the *author* of the entity. By sender here we're
#     talking about the sender of the *request*. If this object is being relayed by the sender, the author
#     could actually be a different identity.
# 
#     :arg request: Request object of type RequestType - note not a HTTP request even though the structure is similar
#     :arg user: User that will be passed to `protocol.receive` (only required on private encrypted content)
#         MUST have a `private_key` and `id` if given.
#     :arg sender_key_fetcher: Function that accepts sender handle and returns public key (optional)
#     :arg skip_author_verification: Don't verify sender (test purposes, false default)
#     :returns: Tuple of sender id, protocol name and list of entity objects
#     """
#     logger.debug("handle_receive: processing request: %s", request)
#     found_protocol = identify_protocol_by_request(request)
# 
#     logger.debug("handle_receive: using protocol %s", found_protocol.PROTOCOL_NAME)
#     protocol = found_protocol.Protocol()
#     sender, message = protocol.receive(
#         request, user, sender_key_fetcher, skip_author_verification=skip_author_verification)
#     logger.debug("handle_receive: sender %s, message %s", sender, message)
# 
#     mappers = importlib.import_module("federation.entities.%s.mappers" % found_protocol.PROTOCOL_NAME)
#     entities = mappers.message_to_objects(message, sender, sender_key_fetcher, user)
#     logger.debug("handle_receive: entities %s", entities)
# 
#     return sender, found_protocol.PROTOCOL_NAME, entities
# 
# Path: federation/types.py
# class RequestType:
#     """
#     Emulates structure of a Django HttpRequest for compatibility.
#     """
#     body: Union[str, bytes] = attr.ib()
# 
#     # Required when dealing with incoming AP payloads
#     headers: Dict = attr.ib(default=None)
#     method: str = attr.ib(default=None)
#     url: str = attr.ib(default=None)


# Path: federation/tests/test_inbound.py
from unittest.mock import patch
from federation.exceptions import NoSuitableProtocolFoundError
from federation.inbound import handle_receive
from federation.protocols.diaspora.protocol import Protocol
from federation.tests.fixtures.payloads import DIASPORA_PUBLIC_PAYLOAD
from federation.types import RequestType
import pytest





class TestHandleReceiveProtocolIdentification:
    def test_handle_receive_routes_to_identified_protocol(self):
        payload = RequestType(body=DIASPORA_PUBLIC_PAYLOAD)
        with patch.object(
                    Protocol,
                    'receive',
                    return_value=("foobar@domain.tld", "<foobar></foobar>")) as mock_receive,\
                patch(
                    "federation.entities.diaspora.mappers.message_to_objects",
                    return_value=[]) as mock_message_to_objects:
            handle_receive(payload)
            assert mock_receive.called

    def test_handle_receive_raises_on_unidentified_protocol(self):
        payload = RequestType(body="foobar")
        with pytest.raises(NoSuitableProtocolFoundError):

            handle_receive(payload)