Extract MailMocker

This commit is contained in:
Daniel Bankmann 2024-08-25 10:55:19 +02:00 committed by shamoon
parent 35155afce9
commit 1de33baa2a

View File

@ -298,16 +298,13 @@ def reset_bogus_mailbox(bogus_mailbox: BogusMailBox, message_builder: MessageBui
bogus_mailbox.updateClient() bogus_mailbox.updateClient()
@mock.patch("paperless_mail.mail.magic.from_buffer", fake_magic_from_buffer) class MailMocker(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
class TestMail(
DirectoriesMixin,
FileSystemAssertsMixin,
TestCase,
):
def setUp(self): def setUp(self):
self.bogus_mailbox = BogusMailBox() self.bogus_mailbox = BogusMailBox()
self.messageBuilder = MessageBuilder() self.messageBuilder = MessageBuilder()
reset_bogus_mailbox(self.bogus_mailbox, self.messageBuilder)
patcher = mock.patch("paperless_mail.mail.MailBox") patcher = mock.patch("paperless_mail.mail.MailBox")
m = patcher.start() m = patcher.start()
m.return_value = self.bogus_mailbox m.return_value = self.bogus_mailbox
@ -317,8 +314,77 @@ class TestMail(
self._queue_consumption_tasks_mock = patcher.start() self._queue_consumption_tasks_mock = patcher.start()
self.addCleanup(patcher.stop) self.addCleanup(patcher.stop)
reset_bogus_mailbox(self.bogus_mailbox, self.messageBuilder) super().setUp()
def assert_queue_consumption_tasks_call_args(
self,
expected_call_args: list[list[dict[str, str]]],
):
"""
Verifies that queue_consumption_tasks has been called with the expected arguments.
expected_call_args is the following format:
* List of calls to queue_consumption_tasks, called once per mail, where each element is:
* List of signatures for the consume_file task, where each element is:
* dictionary containing arguments that need to be present in the consume_file signature.
"""
# assert number of calls to queue_consumption_tasks match
self.assertEqual(
len(self._queue_consumption_tasks_mock.call_args_list),
len(expected_call_args),
)
for (mock_args, mock_kwargs), expected_signatures in zip(
self._queue_consumption_tasks_mock.call_args_list,
expected_call_args,
):
consume_tasks = mock_kwargs["consume_tasks"]
# assert number of consume_file tasks match
self.assertEqual(len(consume_tasks), len(expected_signatures))
for consume_task, expected_signature in zip(
consume_tasks,
expected_signatures,
):
input_doc, overrides = consume_task.args
# assert the file exists
self.assertIsFile(input_doc.original_file)
# assert all expected arguments are present in the signature
for key, value in expected_signature.items():
if key == "override_correspondent_id":
self.assertEqual(overrides.correspondent_id, value)
elif key == "override_filename":
self.assertEqual(overrides.filename, value)
elif key == "override_title":
self.assertEqual(overrides.title, value)
else:
self.fail("No match for expected arg")
def apply_mail_actions(self):
"""
Applies pending actions to mails by inspecting calls to the queue_consumption_tasks method.
"""
for args, kwargs in self._queue_consumption_tasks_mock.call_args_list:
message = kwargs["message"]
rule = kwargs["rule"]
apply_mail_action([], rule.pk, message.uid, message.subject, message.date)
@mock.patch("paperless_mail.mail.magic.from_buffer", fake_magic_from_buffer)
class TestMail(
DirectoriesMixin,
FileSystemAssertsMixin,
TestCase,
):
def setUp(self):
self.mailMocker = MailMocker()
self.mailMocker.setUp()
self.mail_account_handler = MailAccountHandler() self.mail_account_handler = MailAccountHandler()
super().setUp() super().setUp()
@ -405,7 +471,7 @@ class TestMail(
self.assertEqual(handler._get_title(message, att, rule), None) self.assertEqual(handler._get_title(message, att, rule), None)
def test_handle_message(self): def test_handle_message(self):
message = self.messageBuilder.create_message( message = self.mailMocker.messageBuilder.create_message(
subject="the message title", subject="the message title",
from_="Myself", from_="Myself",
attachments=2, attachments=2,
@ -422,9 +488,9 @@ class TestMail(
self.assertEqual(result, 2) self.assertEqual(result, 2)
self._queue_consumption_tasks_mock.assert_called() self.mailMocker._queue_consumption_tasks_mock.assert_called()
self.assert_queue_consumption_tasks_call_args( self.mailMocker.assert_queue_consumption_tasks_call_args(
[ [
[ [
{"override_title": "file_0", "override_filename": "file_0.pdf"}, {"override_title": "file_0", "override_filename": "file_0.pdf"},
@ -441,11 +507,11 @@ class TestMail(
result = self.mail_account_handler._handle_message(message, rule) result = self.mail_account_handler._handle_message(message, rule)
self._queue_consumption_tasks_mock.assert_not_called() self.mailMocker._queue_consumption_tasks_mock.assert_not_called()
self.assertEqual(result, 0) self.assertEqual(result, 0)
def test_handle_unknown_mime_type(self): def test_handle_unknown_mime_type(self):
message = self.messageBuilder.create_message( message = self.mailMocker.messageBuilder.create_message(
attachments=[ attachments=[
_AttachmentDef(filename="f1.pdf"), _AttachmentDef(filename="f1.pdf"),
_AttachmentDef( _AttachmentDef(
@ -465,7 +531,7 @@ class TestMail(
result = self.mail_account_handler._handle_message(message, rule) result = self.mail_account_handler._handle_message(message, rule)
self.assertEqual(result, 1) self.assertEqual(result, 1)
self.assert_queue_consumption_tasks_call_args( self.mailMocker.assert_queue_consumption_tasks_call_args(
[ [
[ [
{"override_filename": "f1.pdf"}, {"override_filename": "f1.pdf"},
@ -474,7 +540,7 @@ class TestMail(
) )
def test_handle_disposition(self): def test_handle_disposition(self):
message = self.messageBuilder.create_message( message = self.mailMocker.messageBuilder.create_message(
attachments=[ attachments=[
_AttachmentDef( _AttachmentDef(
filename="f1.pdf", filename="f1.pdf",
@ -493,7 +559,7 @@ class TestMail(
result = self.mail_account_handler._handle_message(message, rule) result = self.mail_account_handler._handle_message(message, rule)
self.assertEqual(result, 1) self.assertEqual(result, 1)
self.assert_queue_consumption_tasks_call_args( self.mailMocker.assert_queue_consumption_tasks_call_args(
[ [
[ [
{"override_filename": "f2.pdf"}, {"override_filename": "f2.pdf"},
@ -502,7 +568,7 @@ class TestMail(
) )
def test_handle_inline_files(self): def test_handle_inline_files(self):
message = self.messageBuilder.create_message( message = self.mailMocker.messageBuilder.create_message(
attachments=[ attachments=[
_AttachmentDef( _AttachmentDef(
filename="f1.pdf", filename="f1.pdf",
@ -522,7 +588,7 @@ class TestMail(
result = self.mail_account_handler._handle_message(message, rule) result = self.mail_account_handler._handle_message(message, rule)
self.assertEqual(result, 2) self.assertEqual(result, 2)
self.assert_queue_consumption_tasks_call_args( self.mailMocker.assert_queue_consumption_tasks_call_args(
[ [
[ [
{"override_filename": "f1.pdf"}, {"override_filename": "f1.pdf"},
@ -542,7 +608,7 @@ class TestMail(
- Mail action should not be performed for files excluded - Mail action should not be performed for files excluded
- Mail action should be performed for files included - Mail action should be performed for files included
""" """
message = self.messageBuilder.create_message( message = self.mailMocker.messageBuilder.create_message(
attachments=[ attachments=[
_AttachmentDef(filename="f1.pdf"), _AttachmentDef(filename="f1.pdf"),
_AttachmentDef(filename="f2.pdf"), _AttachmentDef(filename="f2.pdf"),
@ -626,7 +692,7 @@ class TestMail(
for test_case in tests: for test_case in tests:
with self.subTest(msg=test_case.name): with self.subTest(msg=test_case.name):
self._queue_consumption_tasks_mock.reset_mock() self.mailMocker._queue_consumption_tasks_mock.reset_mock()
account = MailAccount(name=str(uuid.uuid4())) account = MailAccount(name=str(uuid.uuid4()))
account.save() account.save()
rule = MailRule( rule = MailRule(
@ -639,7 +705,7 @@ class TestMail(
rule.save() rule.save()
self.mail_account_handler._handle_message(message, rule) self.mail_account_handler._handle_message(message, rule)
self.assert_queue_consumption_tasks_call_args( self.mailMocker.assert_queue_consumption_tasks_call_args(
[ [
[{"override_filename": m} for m in test_case.expected_matches], [{"override_filename": m} for m in test_case.expected_matches],
], ],
@ -654,7 +720,7 @@ class TestMail(
THEN: THEN:
- Mail action should not be performed - Mail action should not be performed
""" """
message = self.messageBuilder.create_message( message = self.mailMocker.messageBuilder.create_message(
attachments=[ attachments=[
_AttachmentDef( _AttachmentDef(
filename="test.png", filename="test.png",
@ -662,7 +728,7 @@ class TestMail(
), ),
], ],
) )
self.bogus_mailbox.messages.append(message) self.mailMocker.bogus_mailbox.messages.append(message)
account = MailAccount.objects.create( account = MailAccount.objects.create(
name="test", name="test",
imap_server="", imap_server="",
@ -680,12 +746,12 @@ class TestMail(
) )
rule.save() rule.save()
self.assertEqual(len(self.bogus_mailbox.messages), 4) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 4)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(len(self.bogus_mailbox.messages), 1) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 1)
def test_handle_mail_account_mark_read(self): def test_handle_mail_account_mark_read(self):
account = MailAccount.objects.create( account = MailAccount.objects.create(
@ -701,14 +767,14 @@ class TestMail(
action=MailRule.MailAction.MARK_READ, action=MailRule.MailAction.MARK_READ,
) )
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
self.assertEqual(len(self.bogus_mailbox.fetch("UNSEEN", False)), 2) self.assertEqual(len(self.mailMocker.bogus_mailbox.fetch("UNSEEN", False)), 2)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(len(self.bogus_mailbox.fetch("UNSEEN", False)), 0) self.assertEqual(len(self.mailMocker.bogus_mailbox.fetch("UNSEEN", False)), 0)
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
def test_handle_mail_account_delete(self): def test_handle_mail_account_delete(self):
account = MailAccount.objects.create( account = MailAccount.objects.create(
@ -725,12 +791,12 @@ class TestMail(
filter_subject="Invoice", filter_subject="Invoice",
) )
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(len(self.bogus_mailbox.messages), 1) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 1)
def test_handle_mail_account_delete_no_filters(self): def test_handle_mail_account_delete_no_filters(self):
account = MailAccount.objects.create( account = MailAccount.objects.create(
@ -747,12 +813,12 @@ class TestMail(
maximum_age=0, maximum_age=0,
) )
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(len(self.bogus_mailbox.messages), 0) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 0)
def test_handle_mail_account_flag(self): def test_handle_mail_account_flag(self):
account = MailAccount.objects.create( account = MailAccount.objects.create(
@ -769,14 +835,20 @@ class TestMail(
filter_subject="Invoice", filter_subject="Invoice",
) )
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
self.assertEqual(len(self.bogus_mailbox.fetch("UNFLAGGED", False)), 2) self.assertEqual(
len(self.mailMocker.bogus_mailbox.fetch("UNFLAGGED", False)),
2,
)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(len(self.bogus_mailbox.fetch("UNFLAGGED", False)), 1) self.assertEqual(
self.assertEqual(len(self.bogus_mailbox.messages), 3) len(self.mailMocker.bogus_mailbox.fetch("UNFLAGGED", False)),
1,
)
self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
@pytest.mark.flaky(reruns=4) @pytest.mark.flaky(reruns=4)
def test_handle_mail_account_move(self): def test_handle_mail_account_move(self):
@ -795,14 +867,14 @@ class TestMail(
filter_subject="Claim", filter_subject="Claim",
) )
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
self.assertEqual(len(self.bogus_mailbox.messages_spam), 0) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages_spam), 0)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(len(self.bogus_mailbox.messages), 2) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 2)
self.assertEqual(len(self.bogus_mailbox.messages_spam), 1) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages_spam), 1)
def test_handle_mail_account_move_no_filters(self): def test_handle_mail_account_move_no_filters(self):
account = MailAccount.objects.create( account = MailAccount.objects.create(
@ -820,14 +892,14 @@ class TestMail(
maximum_age=0, maximum_age=0,
) )
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
self.assertEqual(len(self.bogus_mailbox.messages_spam), 0) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages_spam), 0)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(len(self.bogus_mailbox.messages), 0) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 0)
self.assertEqual(len(self.bogus_mailbox.messages_spam), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages_spam), 3)
def test_handle_mail_account_tag(self): def test_handle_mail_account_tag(self):
account = MailAccount.objects.create( account = MailAccount.objects.create(
@ -844,18 +916,24 @@ class TestMail(
action_parameter="processed", action_parameter="processed",
) )
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
self.assertEqual(len(self.bogus_mailbox.fetch("UNKEYWORD processed", False)), 2) self.assertEqual(
len(self.mailMocker.bogus_mailbox.fetch("UNKEYWORD processed", False)),
2,
)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
self.assertEqual(len(self.bogus_mailbox.fetch("UNKEYWORD processed", False)), 0) self.assertEqual(
len(self.mailMocker.bogus_mailbox.fetch("UNKEYWORD processed", False)),
0,
)
def test_handle_mail_account_tag_gmail(self): def test_handle_mail_account_tag_gmail(self):
self.bogus_mailbox._host = "imap.gmail.com" self.mailMocker.bogus_mailbox._host = "imap.gmail.com"
self.bogus_mailbox.client.capabilities = ["X-GM-EXT-1"] self.mailMocker.bogus_mailbox.client.capabilities = ["X-GM-EXT-1"]
account = MailAccount.objects.create( account = MailAccount.objects.create(
name="test", name="test",
@ -871,15 +949,15 @@ class TestMail(
action_parameter="processed", action_parameter="processed",
) )
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
criteria = NOT(gmail_label="processed") criteria = NOT(gmail_label="processed")
self.assertEqual(len(self.bogus_mailbox.fetch(criteria, False)), 2) self.assertEqual(len(self.mailMocker.bogus_mailbox.fetch(criteria, False)), 2)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(len(self.bogus_mailbox.fetch(criteria, False)), 0) self.assertEqual(len(self.mailMocker.bogus_mailbox.fetch(criteria, False)), 0)
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
def test_tag_mail_action_applemail_wrong_input(self): def test_tag_mail_action_applemail_wrong_input(self):
self.assertRaises( self.assertRaises(
@ -906,14 +984,20 @@ class TestMail(
action_parameter="apple:green", action_parameter="apple:green",
) )
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
self.assertEqual(len(self.bogus_mailbox.fetch("UNFLAGGED", False)), 2) self.assertEqual(
len(self.mailMocker.bogus_mailbox.fetch("UNFLAGGED", False)),
2,
)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(len(self.bogus_mailbox.fetch("UNFLAGGED", False)), 0) self.assertEqual(
self.assertEqual(len(self.bogus_mailbox.messages), 3) len(self.mailMocker.bogus_mailbox.fetch("UNFLAGGED", False)),
0,
)
self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
def test_error_login(self): def test_error_login(self):
""" """
@ -961,10 +1045,10 @@ class TestMail(
) )
tasks.process_mail_accounts() tasks.process_mail_accounts()
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(len(self.bogus_mailbox.messages), 2) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 2)
self.assertEqual(len(self.bogus_mailbox.messages_spam), 1) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages_spam), 1)
def test_error_skip_rule(self): def test_error_skip_rule(self):
account = MailAccount.objects.create( account = MailAccount.objects.create(
@ -992,10 +1076,10 @@ class TestMail(
) )
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(len(self.bogus_mailbox.messages), 2) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 2)
self.assertEqual(len(self.bogus_mailbox.messages_spam), 1) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages_spam), 1)
def test_error_folder_set(self): def test_error_folder_set(self):
""" """
@ -1021,14 +1105,14 @@ class TestMail(
folder="uuuhhhh", # Invalid folder name folder="uuuhhhh", # Invalid folder name
) )
self.bogus_mailbox.folder.list = mock.Mock( self.mailMocker.bogus_mailbox.folder.list = mock.Mock(
return_value=[FolderInfo("SomeFoldername", "|", ())], return_value=[FolderInfo("SomeFoldername", "|", ())],
) )
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.bogus_mailbox.folder.list.assert_called_once() self.mailMocker.bogus_mailbox.folder.list.assert_called_once()
self._queue_consumption_tasks_mock.assert_not_called() self.mailMocker._queue_consumption_tasks_mock.assert_not_called()
def test_error_folder_set_error_listing(self): def test_error_folder_set_error_listing(self):
""" """
@ -1054,14 +1138,14 @@ class TestMail(
folder="uuuhhhh", # Invalid folder name folder="uuuhhhh", # Invalid folder name
) )
self.bogus_mailbox.folder.list = mock.Mock( self.mailMocker.bogus_mailbox.folder.list = mock.Mock(
side_effect=MailboxFolderSelectError(None, "uhm"), side_effect=MailboxFolderSelectError(None, "uhm"),
) )
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.bogus_mailbox.folder.list.assert_called_once() self.mailMocker.bogus_mailbox.folder.list.assert_called_once()
self._queue_consumption_tasks_mock.assert_not_called() self.mailMocker._queue_consumption_tasks_mock.assert_not_called()
@mock.patch("paperless_mail.mail.MailAccountHandler._get_correspondent") @mock.patch("paperless_mail.mail.MailAccountHandler._get_correspondent")
def test_error_skip_mail(self, m): def test_error_skip_mail(self, m):
@ -1087,14 +1171,17 @@ class TestMail(
) )
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
# test that we still consume mail even if some mails throw errors. # test that we still consume mail even if some mails throw errors.
self.assertEqual(self._queue_consumption_tasks_mock.call_count, 2) self.assertEqual(self.mailMocker._queue_consumption_tasks_mock.call_count, 2)
# faulty mail still in inbox, untouched # faulty mail still in inbox, untouched
self.assertEqual(len(self.bogus_mailbox.messages), 1) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 1)
self.assertEqual(self.bogus_mailbox.messages[0].from_, "amazon@amazon.de") self.assertEqual(
self.mailMocker.bogus_mailbox.messages[0].from_,
"amazon@amazon.de",
)
def test_error_create_correspondent(self): def test_error_create_correspondent(self):
account = MailAccount.objects.create( account = MailAccount.objects.create(
@ -1114,10 +1201,10 @@ class TestMail(
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self._queue_consumption_tasks_mock.assert_called_once() self.mailMocker._queue_consumption_tasks_mock.assert_called_once()
c = Correspondent.objects.get(name="amazon@amazon.de") c = Correspondent.objects.get(name="amazon@amazon.de")
self.assert_queue_consumption_tasks_call_args( self.mailMocker.assert_queue_consumption_tasks_call_args(
[ [
[ [
{"override_correspondent_id": c.id}, {"override_correspondent_id": c.id},
@ -1125,15 +1212,18 @@ class TestMail(
], ],
) )
self._queue_consumption_tasks_mock.reset_mock() self.mailMocker._queue_consumption_tasks_mock.reset_mock()
reset_bogus_mailbox(self.bogus_mailbox, self.messageBuilder) reset_bogus_mailbox(
self.mailMocker.bogus_mailbox,
self.mailMocker.messageBuilder,
)
with mock.patch("paperless_mail.mail.Correspondent.objects.get_or_create") as m: with mock.patch("paperless_mail.mail.Correspondent.objects.get_or_create") as m:
m.side_effect = DatabaseError() m.side_effect = DatabaseError()
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.assert_queue_consumption_tasks_call_args( self.mailMocker.assert_queue_consumption_tasks_call_args(
[ [
[ [
{"override_correspondent_id": None}, {"override_correspondent_id": None},
@ -1171,21 +1261,24 @@ class TestMail(
filter_from=f_from, filter_from=f_from,
filter_to=f_to, filter_to=f_to,
) )
reset_bogus_mailbox(self.bogus_mailbox, self.messageBuilder) reset_bogus_mailbox(
self._queue_consumption_tasks_mock.reset_mock() self.mailMocker.bogus_mailbox,
self.mailMocker.messageBuilder,
)
self.mailMocker._queue_consumption_tasks_mock.reset_mock()
self._queue_consumption_tasks_mock.assert_not_called() self.mailMocker._queue_consumption_tasks_mock.assert_not_called()
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual( self.assertEqual(
len(self.bogus_mailbox.messages), len(self.mailMocker.bogus_mailbox.messages),
3 - expected_mail_count, 3 - expected_mail_count,
) )
self.assertEqual( self.assertEqual(
self._queue_consumption_tasks_mock.call_count, self.mailMocker._queue_consumption_tasks_mock.call_count,
expected_mail_count, expected_mail_count,
) )
@ -1212,16 +1305,16 @@ class TestMail(
action=MailRule.MailAction.MARK_READ, action=MailRule.MailAction.MARK_READ,
) )
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
self._queue_consumption_tasks_mock.assert_not_called() self.mailMocker._queue_consumption_tasks_mock.assert_not_called()
self.assertEqual(len(self.bogus_mailbox.fetch("UNSEEN", False)), 2) self.assertEqual(len(self.mailMocker.bogus_mailbox.fetch("UNSEEN", False)), 2)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(self._queue_consumption_tasks_mock.call_count, 2) self.assertEqual(self.mailMocker._queue_consumption_tasks_mock.call_count, 2)
self.assertEqual(len(self.bogus_mailbox.fetch("UNSEEN", False)), 0) self.assertEqual(len(self.mailMocker.bogus_mailbox.fetch("UNSEEN", False)), 0)
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
def test_auth_plain_fallback_fails_still(self): def test_auth_plain_fallback_fails_still(self):
""" """
@ -1278,75 +1371,16 @@ class TestMail(
action=MailRule.MailAction.MARK_READ, action=MailRule.MailAction.MARK_READ,
) )
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
self.assertEqual(self._queue_consumption_tasks_mock.call_count, 0) self.assertEqual(self.mailMocker._queue_consumption_tasks_mock.call_count, 0)
self.assertEqual(len(self.bogus_mailbox.fetch("UNSEEN", False)), 2) self.assertEqual(len(self.mailMocker.bogus_mailbox.fetch("UNSEEN", False)), 2)
self.mail_account_handler.handle_mail_account(account) self.mail_account_handler.handle_mail_account(account)
self.apply_mail_actions() self.mailMocker.apply_mail_actions()
self.assertEqual(self._queue_consumption_tasks_mock.call_count, 2) self.assertEqual(self.mailMocker._queue_consumption_tasks_mock.call_count, 2)
self.assertEqual(len(self.bogus_mailbox.fetch("UNSEEN", False)), 0) self.assertEqual(len(self.mailMocker.bogus_mailbox.fetch("UNSEEN", False)), 0)
self.assertEqual(len(self.bogus_mailbox.messages), 3) self.assertEqual(len(self.mailMocker.bogus_mailbox.messages), 3)
def assert_queue_consumption_tasks_call_args(
self,
expected_call_args: list[list[dict[str, str]]],
):
"""
Verifies that queue_consumption_tasks has been called with the expected arguments.
expected_call_args is the following format:
* List of calls to queue_consumption_tasks, called once per mail, where each element is:
* List of signatures for the consume_file task, where each element is:
* dictionary containing arguments that need to be present in the consume_file signature.
"""
# assert number of calls to queue_consumption_tasks match
self.assertEqual(
len(self._queue_consumption_tasks_mock.call_args_list),
len(expected_call_args),
)
for (mock_args, mock_kwargs), expected_signatures in zip(
self._queue_consumption_tasks_mock.call_args_list,
expected_call_args,
):
consume_tasks = mock_kwargs["consume_tasks"]
# assert number of consume_file tasks match
self.assertEqual(len(consume_tasks), len(expected_signatures))
for consume_task, expected_signature in zip(
consume_tasks,
expected_signatures,
):
input_doc, overrides = consume_task.args
# assert the file exists
self.assertIsFile(input_doc.original_file)
# assert all expected arguments are present in the signature
for key, value in expected_signature.items():
if key == "override_correspondent_id":
self.assertEqual(overrides.correspondent_id, value)
elif key == "override_filename":
self.assertEqual(overrides.filename, value)
elif key == "override_title":
self.assertEqual(overrides.title, value)
else:
self.fail("No match for expected arg")
def apply_mail_actions(self):
"""
Applies pending actions to mails by inspecting calls to the queue_consumption_tasks method.
"""
for args, kwargs in self._queue_consumption_tasks_mock.call_args_list:
message = kwargs["message"]
rule = kwargs["rule"]
apply_mail_action([], rule.pk, message.uid, message.subject, message.date)
class TestManagementCommand(TestCase): class TestManagementCommand(TestCase):