[IMP] mail: improve tests tooling methods
In this commit we add a method to check MailMail, based on a given record. When having duplicates to differentiate in a given mailing, having just recipients is not sufficient as multiple emails may match a given recipients list. Checking model / res_id is another method for finding emails. This will be used notably to add tests for exclusion list and duplicates management in standard mail composer, outside of mass mailing context. While being at it, use subTests when having loops checking values. That way it is easier to fix tests that have several failing values in the same global assertMailMail_* . Task-3132710 (Mail: Configurable composer) Part-of: odoo/odoo#99482
This commit is contained in:
+95
-62
@@ -329,18 +329,19 @@ class MockEmail(common.BaseCase, MockSmtplibCase):
|
||||
# GATEWAY ASSERTS
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def assertMailMail(self, recipients, status,
|
||||
mail_message=None, author=None,
|
||||
content=None, fields_values=None, email_values=None):
|
||||
""" Assert mail.mail records are created and maybe sent as emails. Allow
|
||||
def _assertMailMail(self, mail, recipients_list,
|
||||
status, author=None,
|
||||
content=None, fields_values=None, email_values=None):
|
||||
""" Assert mail.mail record values and maybe related emails. Allow
|
||||
asserting their content. Records to check are the one generated when
|
||||
using mock (mail.mail and outgoing emails). This method takes partners
|
||||
as source of record fetch and assert.
|
||||
using mock (mail.mail and outgoing emails).
|
||||
|
||||
:param recipients: a ``res.partner`` recordset. See ``_find_mail_mail_wpartners``;
|
||||
:param mail: a ``mail.mail`` record;
|
||||
:param recipients_list: an ``res.partner`` recordset or a list of
|
||||
emails (both are supported, see ``_find_mail_mail_wpartners`` and
|
||||
``_find_mail_mail_wemail``);
|
||||
:param status: mail.mail state used to filter mails. If ``sent`` this method
|
||||
also check that emails have been sent trough gateway;
|
||||
:param mail_message: see ``_find_mail_mail_wpartners``;
|
||||
:param author: see ``_find_mail_mail_wpartners``;
|
||||
:param content: if given, check it is contained within mail html body;
|
||||
:param fields_values: if given, should be a dictionary of field names /
|
||||
@@ -350,52 +351,89 @@ class MockEmail(common.BaseCase, MockSmtplibCase):
|
||||
allowing to check sent email additional values (if any).
|
||||
See ``assertSentEmail``;
|
||||
"""
|
||||
self.assertTrue(bool(mail))
|
||||
if content:
|
||||
self.assertIn(content, mail.body_html)
|
||||
for fname, fvalue in (fields_values or {}).items():
|
||||
with self.subTest(fname=fname, fvalue=fvalue):
|
||||
self.assertEqual(
|
||||
mail[fname], fvalue,
|
||||
'Mail: expected %s for %s, got %s' % (fvalue, fname, mail[fname])
|
||||
)
|
||||
if status == 'sent':
|
||||
for recipient in recipients_list:
|
||||
with self.subTest(recipient=recipient):
|
||||
self.assertSentEmail(
|
||||
email_values['email_from'] if email_values and email_values.get('email_from') else author,
|
||||
[recipient],
|
||||
**(email_values or {})
|
||||
)
|
||||
|
||||
def assertMailMail(self, recipients, status,
|
||||
mail_message=None, author=None,
|
||||
content=None, fields_values=None, email_values=None):
|
||||
""" Assert mail.mail records are created and maybe sent as emails. This
|
||||
method takes partners as source to find mails and check their content.
|
||||
See '_assertMailMail' for more details.
|
||||
|
||||
:param recipients: a ``res.partner`` recordset. See
|
||||
``_find_mail_mail_wpartners``;
|
||||
:param mail_message: used to find the related email;
|
||||
|
||||
See '_assertMailMail' for more details about other parameters.
|
||||
"""
|
||||
found_mail = self._find_mail_mail_wpartners(recipients, status, mail_message=mail_message, author=author)
|
||||
self.assertTrue(bool(found_mail))
|
||||
if content:
|
||||
self.assertIn(content, found_mail.body_html)
|
||||
for fname, fvalue in (fields_values or {}).items():
|
||||
self.assertEqual(
|
||||
found_mail[fname], fvalue,
|
||||
'Mail: expected %s for %s, got %s' % (fvalue, fname, found_mail[fname]))
|
||||
if status == 'sent':
|
||||
for recipient in recipients:
|
||||
self.assertSentEmail(email_values['email_from'] if email_values and email_values.get('email_from') else author, [recipient], **(email_values or {}))
|
||||
self._assertMailMail(
|
||||
found_mail, recipients,
|
||||
status, author=author,
|
||||
content=content, fields_values=fields_values, email_values=email_values,
|
||||
)
|
||||
|
||||
def assertMailMailWEmails(self, emails, status,
|
||||
mail_message=None, author=None,
|
||||
content=None, fields_values=None, email_values=None):
|
||||
""" Assert mail.mail records are created and maybe sent as emails. Allow
|
||||
asserting their content. Records to check are the one generated when
|
||||
using mock (mail.mail and outgoing emails). This method takes emails
|
||||
as source of record fetch and assert.
|
||||
""" Assert mail.mail records are created and maybe sent as emails. This
|
||||
method takes emails as source to find mails and check their content.
|
||||
See '_assertMailMail' for more details.
|
||||
|
||||
:param emails: a list of emails. See ``_find_mail_mail_wemail``;
|
||||
:param status: mail.mail state used to filter mails. If ``sent`` this method
|
||||
also check that emails have been sent trough gateway;
|
||||
:param mail_message: see ``_find_mail_mail_wemail``;
|
||||
:param author: see ``_find_mail_mail_wemail``;;
|
||||
:param content: if given, check it is contained within mail html body;
|
||||
:param fields_values: if given, should be a dictionary of field names /
|
||||
values allowing to check ``mail.mail`` additional values (subject,
|
||||
reply_to, ...);
|
||||
:param email_values: if given, should be a dictionary of keys / values
|
||||
allowing to check sent email additional values (if any).
|
||||
See ``assertSentEmail``;
|
||||
:param mail_message: used to find the related email;
|
||||
|
||||
See '_assertMailMail' for more details about other parameters.
|
||||
"""
|
||||
for email_to in emails:
|
||||
found_mail = self._find_mail_mail_wemail(email_to, status, mail_message=mail_message, author=author)
|
||||
if content:
|
||||
self.assertIn(content, found_mail.body_html)
|
||||
for fname, fvalue in (fields_values or {}).items():
|
||||
self.assertEqual(
|
||||
found_mail[fname], fvalue,
|
||||
'Mail: expected %s for %s, got %s' % (fvalue, fname, found_mail[fname]))
|
||||
if status == 'sent':
|
||||
for email_to in emails:
|
||||
self.assertSentEmail(email_values['email_from'] if email_values and email_values.get('email_from') else author, [email_to], **(email_values or {}))
|
||||
self.assertTrue(bool(found_mail))
|
||||
self._assertMailMail(
|
||||
found_mail, [email_to],
|
||||
status, author=author,
|
||||
content=content, fields_values=fields_values, email_values=email_values,
|
||||
)
|
||||
|
||||
def assertMailMailWRecord(self, record, recipients, status,
|
||||
mail_message=None, author=None,
|
||||
content=None, fields_values=None, email_values=None):
|
||||
""" Assert mail.mail records are created and maybe sent as emails. This
|
||||
method takes a record as source to find mails and check their content
|
||||
using model / res_id. See '_assertMailMail' for more details.
|
||||
|
||||
:param record: a record used to find emails sent related on it.
|
||||
See ``_find_mail_mail_wrecord``;
|
||||
:param mail_message: used to find the related email;
|
||||
|
||||
See '_assertMailMail' for more details about other parameters.
|
||||
"""
|
||||
found_mail = self._find_mail_mail_wrecord(record, mail_message=mail_message, author=author)
|
||||
self.assertTrue(bool(found_mail))
|
||||
self._assertMailMail(
|
||||
found_mail, recipients,
|
||||
status, author=author,
|
||||
content=content, fields_values=fields_values, email_values=email_values,
|
||||
)
|
||||
|
||||
def assertMailMailWId(self, mail_id, status,
|
||||
author=None,
|
||||
content=None, fields_values=None):
|
||||
""" Assert mail.mail records are created and maybe sent as emails. Allow
|
||||
asserting their content. Records to check are the one generated when
|
||||
@@ -403,32 +441,27 @@ class MockEmail(common.BaseCase, MockSmtplibCase):
|
||||
as source of record fetch and assert.
|
||||
|
||||
:param mail_id: a ``mail.mail`` DB ID. See ``_find_mail_mail_wid``;
|
||||
:param status: mail.mail state to check upon found mail;
|
||||
:param content: if given, check it is contained within mail html body;
|
||||
:param fields_values: if given, should be a dictionary of field names /
|
||||
values allowing to check ``mail.mail`` additional values (subject,
|
||||
reply_to, ...);
|
||||
|
||||
For other parameters, see ``_assertMailMail``.
|
||||
"""
|
||||
found_mail = self._find_mail_mail_wid(mail_id)
|
||||
self.assertTrue(bool(found_mail))
|
||||
if status:
|
||||
self.assertEqual(found_mail.state, status)
|
||||
if content:
|
||||
self.assertIn(content, found_mail.body_html)
|
||||
for fname, fvalue in (fields_values or {}).items():
|
||||
self.assertEqual(
|
||||
found_mail[fname], fvalue,
|
||||
'Mail: expected %s for %s, got %s' % (fvalue, fname, found_mail[fname]))
|
||||
self._assertMailMail(
|
||||
found_mail, [], # generally used when recipients are Falsy
|
||||
status, author=author,
|
||||
content=content, fields_values=fields_values,
|
||||
)
|
||||
|
||||
def assertMessageFields(self, message, fields_values):
|
||||
""" Just a quick helper to check a mail.message content by giving directly
|
||||
a dict for fields. Allows to hide a lot of assertEqual under a simple
|
||||
call with a dictionary of expected values. """
|
||||
for fname, fvalue in fields_values.items():
|
||||
self.assertEqual(
|
||||
message[fname], fvalue,
|
||||
'Message: expected %s for %s, got %s' % (fvalue, fname, message[fname])
|
||||
)
|
||||
with self.subTest(fname=fname, fvalue=fvalue):
|
||||
self.assertEqual(
|
||||
message[fname], fvalue,
|
||||
f'Message: expected {fvalue} for {fname}, got {message[fname]}',
|
||||
)
|
||||
|
||||
def assertNoMail(self, recipients, mail_message=None, author=None):
|
||||
""" Check no mail.mail and email was generated during gateway mock. """
|
||||
@@ -1030,22 +1063,22 @@ class MailCommon(common.TransactionCase, MailCase):
|
||||
return cls.user_portal
|
||||
|
||||
@classmethod
|
||||
def _create_records_for_batch(cls, model, count, additional_values=None):
|
||||
def _create_records_for_batch(cls, model, count, additional_values=None, prefix=None):
|
||||
additional_values = additional_values or {}
|
||||
records = cls.env[model]
|
||||
partners = cls.env['res.partner']
|
||||
country_id = cls.env.ref('base.be').id
|
||||
|
||||
base_values = [
|
||||
{'name': 'Test_%s' % idx,
|
||||
{'name': f'{prefix}Test_{idx}',
|
||||
**additional_values,
|
||||
} for idx in range(count)
|
||||
]
|
||||
|
||||
if 'customer_id' in cls.env[model]:
|
||||
partners = cls.env['res.partner'].with_context(**cls._test_context).create([{
|
||||
'name': 'Partner_%s' % idx,
|
||||
'email': '_test_partner_%s@example.com' % idx,
|
||||
'name': f'Partner_{idx}',
|
||||
'email': f'{prefix}test_partner_{idx}@example.com',
|
||||
'country_id': country_id,
|
||||
'mobile': '047500%02d%02d' % (idx, idx)
|
||||
} for idx in range(count)])
|
||||
|
||||
@@ -127,7 +127,7 @@ class MassMailCase(MailCase, MockLinkTracker):
|
||||
self.assertMailMail(partner, state_mapping[status], author=author, content=content, fields_values=fields_values)
|
||||
# specific if email is False -> could have troubles finding it if several falsy traces
|
||||
elif not email and status in ('cancel', 'bounce'):
|
||||
self.assertMailMailWId(recipient_trace.mail_mail_id_int, state_mapping[status], content=content, fields_values=fields_values)
|
||||
self.assertMailMailWId(recipient_trace.mail_mail_id_int, state_mapping[status], author=author, content=content, fields_values=fields_values)
|
||||
else:
|
||||
self.assertMailMailWEmails([email], state_mapping[status], author=author, content=content, fields_values=fields_values)
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ class TestMailComposer(TestMailCommon, TestRecipients):
|
||||
})
|
||||
cls.test_records, cls.test_partners = cls._create_records_for_batch(
|
||||
'mail.test.ticket', 2,
|
||||
additional_values={'user_id': cls.user_employee_2.id}
|
||||
additional_values={'user_id': cls.user_employee_2.id},
|
||||
)
|
||||
|
||||
cls.test_report = cls.env['ir.actions.report'].create({
|
||||
|
||||
Reference in New Issue
Block a user