diff --git a/securedrop_client/api_jobs/uploads.py b/securedrop_client/api_jobs/uploads.py index d5b451fb7b..216c415945 100644 --- a/securedrop_client/api_jobs/uploads.py +++ b/securedrop_client/api_jobs/uploads.py @@ -69,13 +69,6 @@ def call_api(self, api_client: API, session: Session) -> str: message = "Failed to send reply for source {id} due to Exception: {error}".format( id=self.source_uuid, error=e) - # Update draft reply send status to FAILED - reply_status = session.query(ReplySendStatus).filter_by( - name=ReplySendStatusCodes.FAILED.value).one() - draft_reply_db_object.send_status_id = reply_status.id - session.add(draft_reply_db_object) - session.commit() - raise SendReplyJobTimeoutError(message, self.reply_uuid) except Exception as e: message = "Failed to send reply for source {id} due to Exception: {error}".format( diff --git a/securedrop_client/logic.py b/securedrop_client/logic.py index f610bcc740..acc9a1aaa9 100644 --- a/securedrop_client/logic.py +++ b/securedrop_client/logic.py @@ -812,7 +812,10 @@ def on_reply_failure( exception: Union[SendReplyJobError, SendReplyJobTimeoutError] ) -> None: logger.debug('{} failed to send'.format(exception.reply_uuid)) - self.reply_failed.emit(exception.reply_uuid) + + # only emit failure signal for non-timeout errors + if isinstance(exception, SendReplyJobError): + self.reply_failed.emit(exception.reply_uuid) def get_file(self, file_uuid: str) -> db.File: file = storage.get_file(self.session, file_uuid) diff --git a/tests/test_logic.py b/tests/test_logic.py index 68bdcdb8f5..90ba784596 100644 --- a/tests/test_logic.py +++ b/tests/test_logic.py @@ -16,7 +16,7 @@ from securedrop_client.api_jobs.downloads import ( DownloadChecksumMismatchException, DownloadDecryptionException, DownloadException ) -from securedrop_client.api_jobs.uploads import SendReplyJobError +from securedrop_client.api_jobs.uploads import SendReplyJobError, SendReplyJobTimeoutError with open(os.path.join(os.path.dirname(__file__), 'files', 'test-key.gpg.pub.asc')) as f: PUB_KEY = f.read() @@ -1394,6 +1394,23 @@ def test_Controller_on_reply_failure(homedir, mocker, session_maker): reply_succeeded.emit.assert_not_called() +def test_Controller_on_reply_failure_for_timeout(homedir, mocker, session_maker): + ''' + Check that when the method is called, the client emits the correct signal. + ''' + co = Controller('http://localhost', mocker.MagicMock(), session_maker, homedir) + reply_succeeded = mocker.patch.object(co, 'reply_succeeded') + reply_failed = mocker.patch.object(co, 'reply_failed') + debug_logger = mocker.patch('securedrop_client.logic.logger.debug') + + exception = SendReplyJobTimeoutError('mock_error_message', 'mock_reply_uuid') + co.on_reply_failure(exception) + + debug_logger.assert_called_once_with('{} failed to send'.format('mock_reply_uuid')) + reply_failed.emit.assert_not_called() + reply_succeeded.emit.assert_not_called() + + def test_Controller_is_authenticated_property(homedir, mocker, session_maker): ''' Check that the @property `is_authenticated`: