[IMP] mail: add tests for private partners in composer

Add tests showing current behavior of partner_ids fields on composer when
dealing with private partners. Some use cases are added as unit tests

  * default_partner_ids: coming notably from suggested recipients;
  * template usage adding a partner (e.g. partner_to);
  * when not having the rights to see private partners, access error should
    be raised;
  * mail gateway when a private partner sends an email;

X-original-commit: 2153eec790b730761fe50d6bea5cd4bacedce97a
Part-of: odoo/odoo#109522
Co-authored-by: Robin Engels <roen@odoo.com>
This commit is contained in:
Thibault Delavallée
2023-01-10 14:40:58 +01:00
co-authored by Robin Engels
parent 73b1aad8fb
commit a45afdd830
2 changed files with 237 additions and 21 deletions
+193 -5
View File
@@ -2,7 +2,9 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.mail.tests.common import MailCommon
from odoo.tests import tagged, users
from odoo.exceptions import AccessError
from odoo.tests import Form, tagged, users
from odoo.tools import mute_logger
@tagged('mail_composer')
@@ -30,14 +32,199 @@ class TestMailComposer(MailCommon):
</div>"""
cls.mail_template = cls.env['mail.template'].create({
'name': 'Test template with mso conditionals',
'subject': 'MSO FTW',
'auto_delete': True,
'body_html': cls.body_html,
'lang': '{{ object.lang }}',
'auto_delete': True,
'model_id': cls.env.ref('base.model_res_partner').id,
'model_id': cls.env['ir.model']._get_id('res.partner'),
'subject': 'MSO FTW',
'name': 'Test template with mso conditionals',
})
@tagged('mail_composer')
class TestMailComposerForm(TestMailComposer):
""" Test mail composer form view usage. """
@classmethod
def setUpClass(cls):
super(TestMailComposerForm, cls).setUpClass()
cls.user_employee.write({'groups_id': [
(4, cls.env.ref('base.group_private_addresses').id),
(4, cls.env.ref('base.group_partner_manager').id),
]})
cls.partner_private, cls.partner_private_2, cls.partner_classic = cls.env['res.partner'].create([
{
'email': 'private.customer@text.example.com',
'phone': '0032455112233',
'name': 'Private Customer',
'type': 'private',
},
{
'email': 'private.customer.2@test.example.com',
'phone': '0032455445566',
'name': 'Private Customer 2',
'type': 'private',
},
{
'email': 'not.private@test.example.com',
'phone': '0032455778899',
'name': 'Classic Customer',
'type': 'contact',
}
])
@mute_logger('odoo.addons.mail.models.mail_mail')
@users('employee')
def test_composer_default_recipients(self):
""" Test usage of a private partner in composer, as default value """
partner_classic = self.partner_classic.with_env(self.env)
test_record = self.test_record.with_env(self.env)
form = Form(self.env['mail.compose.message'].with_context({
'default_partner_ids': partner_classic.ids,
'default_model': test_record._name,
'default_res_id': test_record.id,
}))
form.body = '<p>Hello</p>'
self.assertEqual(
form.partner_ids._get_ids(), partner_classic.ids,
'Default populates the field'
)
saved_form = form.save()
self.assertEqual(
saved_form.partner_ids, partner_classic,
'Default value is kept at save'
)
with self.mock_mail_gateway():
saved_form._action_send_mail()
message = self.test_record.message_ids[0]
self.assertEqual(message.body, '<p>Hello</p>')
self.assertEqual(message.partner_ids, partner_classic)
self.assertEqual(message.subject, f'{test_record.name}')
@mute_logger('odoo.addons.mail.models.mail_mail')
@users('employee')
def test_composer_default_recipients_private(self):
""" Test usage of a private partner in composer, as default value """
partner_private = self.partner_private.with_env(self.env)
partner_classic = self.partner_classic.with_env(self.env)
test_record = self.test_record.with_env(self.env)
form = Form(self.env['mail.compose.message'].with_context({
'default_partner_ids': (partner_private + partner_classic).ids,
'default_model': test_record._name,
'default_res_id': test_record.id,
}))
form.body = '<p>Hello</p>'
self.assertEqual(
sorted(form.partner_ids._get_ids()),
sorted((partner_private + partner_classic).ids),
'Default populates the field'
)
saved_form = form.save()
self.assertEqual(
# saved_form.partner_ids, partner_private + partner_classic,
saved_form.partner_ids, partner_classic,
'Default value is kept at save (FIXME: loosing private partner)'
)
with self.mock_mail_gateway():
saved_form._action_send_mail()
message = self.test_record.message_ids[0]
self.assertEqual(message.body, '<p>Hello</p>')
# self.assertEqual(message.partner_ids, partner_private + partner_classic)
self.assertEqual(
message.partner_ids, partner_classic,
'FIXME: loosing private partner'
)
self.assertEqual(message.subject, f'{test_record.name}')
@mute_logger('odoo.addons.base.models.ir_rule', 'odoo.addons.mail.models.mail_mail')
@users('employee')
def test_composer_default_recipients_private_norights(self):
""" Test usage of a private partner in composer when not having the
rights to see them, as default value """
self.user_employee.write({'groups_id': [
(3, self.env.ref('base.group_private_addresses').id),
]})
with self.assertRaises(AccessError):
_name = self.partner_private.with_env(self.env).name
partner_classic = self.partner_classic.with_env(self.env)
test_record = self.test_record.with_env(self.env)
with self.assertRaises(AccessError):
_form = Form(self.env['mail.compose.message'].with_context({
'default_partner_ids': (self.partner_private + partner_classic).ids,
'default_model': test_record._name,
'default_res_id': test_record.id,
}))
@mute_logger('odoo.addons.mail.models.mail_mail')
@users('employee')
def test_composer_template_recipients_private(self):
""" Test usage of a private partner in composer, comint from template
value """
email_to_new = 'new.customer@test.example.com'
self.mail_template.write({
'email_to': f'{self.partner_private_2.email_formatted}, {email_to_new}',
'partner_to': f'{self.partner_private.id},{self.partner_classic.id}',
})
template = self.mail_template.with_env(self.env)
partner_private = self.partner_private.with_env(self.env)
partner_private_2 = self.partner_private_2.with_env(self.env)
partner_classic = self.partner_classic.with_env(self.env)
test_record = self.test_record.with_env(self.env)
form = Form(self.env['mail.compose.message'].with_context({
'default_model': test_record._name,
'default_res_id': test_record.id,
'default_template_id': template.id,
}))
# transformation from email_to into partner_ids: find or create
existing_partner = self.env['res.partner'].search(
[('email_normalized', '=', self.partner_private_2.email_normalized)]
)
self.assertEqual(existing_partner, partner_private_2, 'Should find existing private contact')
new_partner = self.env['res.partner'].search(
[('email_normalized', '=', email_to_new)]
)
self.assertEqual(new_partner.type, 'contact', 'Should create a new contact')
self.assertEqual(
sorted(form.partner_ids._get_ids()),
sorted((partner_private + partner_classic + partner_private_2 + new_partner).ids),
'Template populates the field with both email_to and partner_to'
)
saved_form = form.save()
self.assertEqual(
# saved_form.partner_ids, partner_private + partner_classic + partner_private_2 + new_partner,
saved_form.partner_ids, partner_classic + new_partner,
'Template value is kept at save (FIXME: loosing private partner)'
)
with self.mock_mail_gateway():
saved_form._action_send_mail()
message = self.test_record.message_ids[0]
self.assertIn('<h1>Hello sir!</h1>', message.body)
# self.assertEqual(message.partner_ids, partner_private + partner_classic + partner_private_2 + new_partner)
self.assertEqual(
message.partner_ids, partner_classic + new_partner,
'FIXME: loosing private partner'
)
self.assertEqual(message.subject, 'MSO FTW')
@tagged('mail_composer')
class TestMailComposerRendering(TestMailComposer):
""" Test rendering and support of various html tweaks in composer """
@users('employee')
def test_mail_mass_mode_template_with_mso(self):
mail_compose_message = self.env['mail.compose.message'].create({
@@ -55,6 +242,7 @@ class TestMailComposer(MailCommon):
'We must preserve (mso) comments in email html'
)
@mute_logger('odoo.addons.mail.models.mail_mail')
@users('employee')
def test_mail_mass_mode_compose_with_mso(self):
composer = self.env['mail.compose.message'].with_context({
+44 -16
View File
@@ -118,6 +118,7 @@ class TestEmailParsing(TestMailCommon):
class TestMailAlias(TestMailCommon):
@users('employee')
@mute_logger('odoo.addons.base.models.ir_model')
def test_alias_creation(self):
record = self.env['mail.test.container'].create({
'name': 'Test Record',
@@ -309,7 +310,24 @@ class TestMailgateway(TestMailCommon):
@mute_logger('odoo.addons.mail.models.mail_thread')
def test_message_process_followers(self):
""" Incoming email: recognized author not archived and not odoobot: added as follower """
""" Incoming email: recognized author not archived and not odoobot:
added as follower. Also test corner cases: archived, private. """
partner_archived, partner_private = self.env['res.partner'].create([
{
'active': False,
'email': 'archived.customer@text.example.com',
'phone': '0032455112233',
'name': 'Archived Customer',
'type': 'contact',
},
{
'email': 'private.customer@text.example.com',
'phone': '0032455112233',
'name': 'Private Customer',
'type': 'private',
},
])
with self.mock_mail_gateway():
record = self.format_and_process(MAIL_TEMPLATE, self.partner_1.email_formatted, 'groups@test.com')
@@ -335,20 +353,17 @@ class TestMailgateway(TestMailCommon):
'message_process: unrecognized email -> no follower')
# archived partner -> no follower
self.partner_1.active = False
self.partner_1.flush_recordset()
with self.mock_mail_gateway():
record3 = self.format_and_process(
MAIL_TEMPLATE, self.partner_1.email_formatted, 'groups@test.com',
subject='Yet Another Email')
MAIL_TEMPLATE, partner_archived.email_formatted, 'groups@test.com',
subject='Archived Partner')
self.assertEqual(record3.message_ids[0].author_id, self.env['res.partner'])
self.assertEqual(record3.message_ids[0].email_from, self.partner_1.email_formatted)
self.assertEqual(record3.message_ids[0].email_from, partner_archived.email_formatted)
self.assertEqual(record3.message_follower_ids.partner_id, self.env['res.partner'],
'message_process: unrecognized email -> no follower')
'message_process: archived partner -> no follower')
self.assertEqual(record3.message_partner_ids, self.env['res.partner'],
'message_process: unrecognized email -> no follower')
'message_process: archived partner -> no follower')
# partner_root -> never again
odoobot = self.env.ref('base.partner_root')
@@ -362,9 +377,22 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(record4.message_ids[0].author_id, odoobot)
self.assertEqual(record4.message_ids[0].email_from, odoobot.email_formatted)
self.assertEqual(record4.message_follower_ids.partner_id, self.env['res.partner'],
'message_process: unrecognized email -> no follower')
'message_process: odoobot -> no follower')
self.assertEqual(record4.message_partner_ids, self.env['res.partner'],
'message_process: unrecognized email -> no follower')
'message_process: odoobot -> no follower')
# private partner
with self.mock_mail_gateway():
record5 = self.format_and_process(
MAIL_TEMPLATE, partner_private.email_formatted, 'groups@test.com',
subject='Private Partner')
self.assertEqual(record5.message_ids[0].author_id, partner_private)
self.assertEqual(record5.message_ids[0].email_from, partner_private.email_formatted)
self.assertEqual(record5.message_follower_ids.partner_id, partner_private,
'message_process: private partner is recognized')
self.assertEqual(record5.message_partner_ids, partner_private,
'message_process: private partner is recognized')
# --------------------------------------------------
# Author recognition
@@ -399,7 +427,7 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(record.message_ids[0].email_from, self.partner_1.email)
self.assertNotSentEmail() # No notification / bounce should be sent
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink')
def test_message_process_email_partner_find(self):
""" Finding the partner based on email, based on partner / user / follower """
self.alias.write({'alias_force_thread_id': self.test_record.id})
@@ -720,7 +748,7 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(record.message_ids[0].create_uid, self.user_employee)
self.assertEqual(record.message_ids[0].author_id, self.user_employee.partner_id)
@mute_logger('odoo.addons.mail.models.mail_thread')
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink')
def test_message_process_create_uid_email_follower(self):
self.alias.write({
'alias_parent_model_id': self.test_model.id,
@@ -1017,7 +1045,7 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(self.partner_1.message_bounce, 0)
self.assertEqual(self.test_record.message_bounce, 1)
@mute_logger('odoo.addons.mail.models.mail_thread')
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink')
def test_message_process_bounce_records_channel(self):
""" Test blacklist allow to multi-bounce and auto update of mail.channel """
other_record = self.env['mail.test.gateway'].create({
@@ -1090,7 +1118,7 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(len(self.test_record.message_ids), init_msg_count + 1)
self.assertEqual(self.fake_email.child_ids, self.test_record.message_ids[0])
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink', 'odoo.addons.mail.models.mail_mail', 'odoo.tests')
def test_message_process_references_multi_parent(self):
""" Incoming email with multiple references """
reply1 = self._create_gateway_message(
@@ -1149,7 +1177,7 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(new_msg.parent_id, self.fake_email, 'Mail: flattening attach to original message')
self.assertEqual(new_msg.subtype_id, self.env.ref('mail.mt_comment'), 'Mail: parent should be a comment (before flattening)')
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink', 'odoo.addons.mail.models.mail_mail', 'odoo.tests')
def test_message_process_references_multi_parent_notflat(self):
""" Incoming email with multiple references with ``_mail_flat_thread``
being False (mail.group/mail.channel behavior like). """