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