async def test_on_interaction_when_json_encode_fails(
        self,
        mock_interaction_server: interaction_server_impl.InteractionServer,
        mock_entity_factory: entity_factory_impl.EntityFactoryImpl,
    ):
        mock_interaction_server._public_key = mock.Mock()
        mock_exception = TypeError("OK")
        mock_interaction_server._dumps = mock.Mock(side_effect=mock_exception)
        mock_entity_factory.deserialize_interaction.return_value = base_interactions.PartialInteraction(
            app=None, id=123, application_id=541324, type=2, token="ok", version=1
        )
        mock_builder = mock.Mock(build=mock.Mock(return_value=({"ok": "No"}, [])))
        mock_interaction_server.set_listener(
            base_interactions.PartialInteraction, mock.AsyncMock(return_value=mock_builder)
        )

        with mock.patch.object(asyncio, "get_running_loop") as get_running_loop:
            result = await mock_interaction_server.on_interaction(b'{"type": 2}', b"signature", b"timestamp")

            get_running_loop.return_value.call_exception_handler.assert_called_once_with(
                {"message": "Exception occurred during interaction dispatch", "exception": mock_exception}
            )

        assert result.content_type == "text/plain; charset=UTF-8"
        assert result.files == ()
        assert result.headers is None
        assert result.payload == b"Exception occurred during interaction dispatch"
        assert result.status_code == 500
    async def test_on_interaction(
        self,
        mock_interaction_server: interaction_server_impl.InteractionServer,
        mock_entity_factory: entity_factory_impl.EntityFactoryImpl,
        public_key: bytes,
        valid_edd25519: bytes,
        valid_payload: bytes,
    ):
        mock_interaction_server._public_key = nacl.signing.VerifyKey(public_key)
        mock_file_1 = mock.Mock()
        mock_file_2 = mock.Mock()
        mock_entity_factory.deserialize_interaction.return_value = base_interactions.PartialInteraction(
            app=None, id=123, application_id=541324, type=2, token="ok", version=1
        )
        mock_builder = mock.Mock(build=mock.Mock(return_value=({"ok": "No boomer"}, [mock_file_1, mock_file_2])))
        mock_listener = mock.AsyncMock(return_value=mock_builder)
        mock_interaction_server.set_listener(base_interactions.PartialInteraction, mock_listener)

        result = await mock_interaction_server.on_interaction(*valid_edd25519)

        mock_listener.assert_awaited_once_with(mock_entity_factory.deserialize_interaction.return_value)
        mock_builder.build.assert_called_once_with(mock_entity_factory)
        mock_entity_factory.deserialize_interaction.assert_called_once_with(valid_payload)
        assert result.content_type == "application/json; charset=UTF-8"
        assert result.files == [mock_file_1, mock_file_2]
        assert result.headers is None
        assert result.payload == b'{"ok": "No boomer"}'
        assert result.status_code == 200
    async def test_on_interaction_on_ping(self, mock_interaction_server: interaction_server_impl.InteractionServer):
        mock_interaction_server._public_key = mock.Mock()

        result = await mock_interaction_server.on_interaction(b'{"type": 1}', b"signature", b"timestamp")

        assert result.content_type == "application/json; charset=UTF-8"
        assert result.files == ()
        assert result.headers is None
        assert result.payload == b'{"type": 1}'
        assert result.status_code == 200
    async def test_on_interaction_when_missing_type_key(
        self, mock_interaction_server: interaction_server_impl.InteractionServer
    ):
        mock_interaction_server._public_key = mock.Mock()

        result = await mock_interaction_server.on_interaction(b'{"key": "OK"}', b"signature", b"timestamp")

        assert result.content_type == "text/plain; charset=UTF-8"
        assert result.files == ()
        assert result.headers is None
        assert result.payload == b"Missing required 'type' field in payload"
        assert result.status_code == 400
    async def test_on_interaction_when_bad_body(
        self, mock_interaction_server: interaction_server_impl.InteractionServer, body: bytes
    ):
        mock_interaction_server._public_key = mock.Mock()

        result = await mock_interaction_server.on_interaction(body, b"signature", b"timestamp")

        assert result.content_type == "text/plain; charset=UTF-8"
        assert result.files == ()
        assert result.headers is None
        assert result.payload == b"Invalid JSON body"
        assert result.status_code == 400
    async def test__fetch_public_key_when_public_key_already_set(
        self, mock_interaction_server: interaction_server_impl.InteractionServer
    ):
        mock_lock = mock.AsyncMock()
        mock_public_key = object()
        mock_interaction_server._application_fetch_lock = mock_lock
        mock_interaction_server._public_key = mock_public_key

        assert await mock_interaction_server._fetch_public_key() is mock_public_key

        mock_lock.__aenter__.assert_awaited_once()
        mock_lock.__aexit__.assert_awaited_once()
    async def test_on_interaction_when_no_registered_listener(
        self,
        mock_interaction_server: interaction_server_impl.InteractionServer,
        mock_entity_factory: entity_factory_impl.EntityFactoryImpl,
    ):
        mock_interaction_server._public_key = mock.Mock()

        result = await mock_interaction_server.on_interaction(b'{"type": 2}', b"signature", b"timestamp")

        assert result.content_type == "text/plain; charset=UTF-8"
        assert result.files == ()
        assert result.headers is None
        assert result.payload == b"Handler not set for this interaction type"
        assert result.status_code == 501
    async def test_on_interaction_on_deserialize_unrecognised_entity_error(
        self,
        mock_interaction_server: interaction_server_impl.InteractionServer,
        mock_entity_factory: entity_factory_impl.EntityFactoryImpl,
    ):
        mock_interaction_server._public_key = mock.Mock()
        mock_entity_factory.deserialize_interaction.side_effect = errors.UnrecognisedEntityError("blah")

        result = await mock_interaction_server.on_interaction(b'{"type": 2}', b"signature", b"timestamp")

        assert result.content_type == "text/plain; charset=UTF-8"
        assert result.files == ()
        assert result.headers is None
        assert result.payload == b"Interaction type not implemented"
        assert result.status_code == 501
    async def test_on_interaction_when_public_key_mismatch(
        self,
        mock_interaction_server: interaction_server_impl.InteractionServer,
        public_key: bytes,
        invalid_ed25519: bytes,
    ):
        mock_interaction_server._public_key = nacl.signing.VerifyKey(public_key)

        result = await mock_interaction_server.on_interaction(*invalid_ed25519)

        assert result.content_type == "text/plain; charset=UTF-8"
        assert result.files == ()
        assert result.headers is None
        assert result.payload == b"Invalid request signature"
        assert result.status_code == 400
    async def test_on_interaction_calls__fetch_public_key(
        self, mock_interaction_server: interaction_server_impl.InteractionServer
    ):
        mock_fetcher = mock.AsyncMock(
            return_value=mock.Mock(verify=mock.Mock(side_effect=nacl.exceptions.BadSignatureError))
        )
        mock_interaction_server._public_key = None
        mock_interaction_server._fetch_public_key = mock_fetcher

        result = await mock_interaction_server.on_interaction(b"body", b"signature", b"timestamp")

        mock_fetcher.assert_awaited_once()
        mock_fetcher.return_value.verify.assert_called_once_with(b"timestampbody", b"signature")
        assert result.content_type == "text/plain; charset=UTF-8"
        assert result.files == ()
        assert result.headers is None
        assert result.payload == b"Invalid request signature"
        assert result.status_code == 400
    async def test_on_interaction_on_failed_deserialize(
        self,
        mock_interaction_server: interaction_server_impl.InteractionServer,
        mock_entity_factory: entity_factory_impl.EntityFactoryImpl,
    ):
        mock_interaction_server._public_key = mock.Mock()
        mock_exception = TypeError("OK")
        mock_entity_factory.deserialize_interaction.side_effect = mock_exception

        with mock.patch.object(asyncio, "get_running_loop") as get_running_loop:
            result = await mock_interaction_server.on_interaction(b'{"type": 2}', b"signature", b"timestamp")

            get_running_loop.return_value.call_exception_handler.assert_called_once_with(
                {"message": "Exception occurred during interaction deserialization", "exception": mock_exception}
            )

        assert result.content_type == "text/plain; charset=UTF-8"
        assert result.files == ()
        assert result.headers is None
        assert result.payload == b"Exception occurred during interaction deserialization"
        assert result.status_code == 500