diff --git a/addons/test_mail/tests/__init__.py b/addons/test_mail/tests/__init__.py index 00691b6ffca..78d3b1516b6 100644 --- a/addons/test_mail/tests/__init__.py +++ b/addons/test_mail/tests/__init__.py @@ -1,22 +1,20 @@ # -*- coding: utf-8 -*- +from . import test_invite +from . import test_ir_actions +from . import test_discuss from . import test_mail_activity from . import test_mail_followers from . import test_mail_message from . import test_mail_mail -from . import test_mail_race -from . import test_mail_resend -from . import test_mail_cc from . import test_mail_channel from . import test_mail_gateway +from . import test_mail_redirect from . import test_mail_template -from . import test_message_compose +from . import test_message_composer +from . import test_message_management +from . import test_message_post from . import test_message_track -from . import test_invite -from . import test_ir_actions -from . import test_update_notification -from . import test_discuss -from . import test_performance -from . import test_res_users from . import test_odoobot -from . import test_multi_company +from . import test_performance +from . import test_update_notification diff --git a/addons/test_mail/tests/common.py b/addons/test_mail/tests/common.py index d3c41a16ab1..17d8594a7d9 100644 --- a/addons/test_mail/tests/common.py +++ b/addons/test_mail/tests/common.py @@ -27,15 +27,43 @@ class BaseFunctionalTest(common.SavepointCase): def setUpClass(cls): super(BaseFunctionalTest, cls).setUpClass() - cls.user_employee = mail_new_test_user(cls.env, login='ernest', groups='base.group_user', signature='--\nErnest', name='Ernest Employee') + cls.user_employee = mail_new_test_user(cls.env, login='employee', groups='base.group_user', signature='--\nErnest', name='Ernest Employee') cls.partner_employee = cls.user_employee.partner_id cls.user_admin = cls.env.ref('base.user_admin') cls.partner_admin = cls.env.ref('base.partner_admin') + @classmethod + def _create_channel_listener(cls): cls.channel_listen = cls.env['mail.channel'].with_context(cls._test_context).create({'name': 'Listener'}) - cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) + @classmethod + def _create_portal_user(cls): + cls.user_portal = mail_new_test_user(cls.env, login='chell', groups='base.group_portal', name='Chell Gladys') + cls.partner_portal = cls.user_portal.partner_id + + @classmethod + def _create_template(cls, model, template_values=None): + create_values = { + 'name': 'TestTemplate', + 'subject': 'About ${object.name}', + 'body_html': '
Hello ${object.name}
', + 'model_id': cls.env['ir.model']._get(model).id, + 'user_signature': False, + } + if template_values: + create_values.update(template_values) + cls.email_template = cls.env['mail.template'].create(create_values) + return cls.email_template + + @classmethod + def _init_mail_gateway(cls): + cls.alias_domain = 'test.com' + cls.alias_catchall = 'catchall.test' + cls.alias_bounce = 'bounce.test' + cls.env['ir.config_parameter'].set_param('mail.bounce.alias', cls.alias_bounce) + cls.env['ir.config_parameter'].set_param('mail.catchall.domain', cls.alias_domain) + cls.env['ir.config_parameter'].set_param('mail.catchall.alias', cls.alias_catchall) @classmethod def _reset_mail_context(cls, record): @@ -62,6 +90,8 @@ class BaseFunctionalTest(common.SavepointCase): init[partner] = { 'na_counter': len([n for n in init_notifs if n.res_partner_id == partner and not n.is_read]), } + if hasattr(self, '_init_mock_build_email'): + self._init_mock_build_email() yield finally: new_notifications = self.env['mail.notification'].sudo().search([ @@ -143,12 +173,27 @@ class BaseFunctionalTest(common.SavepointCase): else: raise AssertionError('Keys %s not found (expected: %s - returned: %s)' % (not_found_keys, repr(expected), repr(notif_messages))) + def assertTracking(self, message, data): + tracking_values = message.sudo().tracking_value_ids + for field_name, value_type, old_value, new_value in data: + tracking = tracking_values.filtered(lambda track: track.field == field_name) + self.assertEqual(len(tracking), 1) + if value_type in ('char', 'integer'): + self.assertEqual(tracking.old_value_char, old_value) + self.assertEqual(tracking.new_value_char, new_value) + elif value_type in ('many2one'): + self.assertEqual(tracking.old_value_integer, old_value and old_value.id or False) + self.assertEqual(tracking.new_value_integer, new_value and new_value.id or False) + self.assertEqual(tracking.old_value_char, old_value and old_value.display_name or '') + self.assertEqual(tracking.new_value_char, new_value and new_value.display_name or '') + else: + self.assertEqual(1, 0) + @contextmanager def sudo(self, login): old_uid = self.uid try: user = self.env['res.users'].sudo().search([('login', '=', login)]) - self.test_record_old = self.test_record # switch user self.uid = user.id self.env = self.env(user=self.uid) diff --git a/addons/test_mail/tests/test_discuss.py b/addons/test_mail/tests/test_discuss.py index 23b707d263f..be255274ea3 100644 --- a/addons/test_mail/tests/test_discuss.py +++ b/addons/test_mail/tests/test_discuss.py @@ -2,11 +2,16 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.addons.test_mail.tests.common import BaseFunctionalTest, TestRecipients, MockEmails -from odoo.addons.test_mail.tests.common import mail_new_test_user +from odoo.tools import mute_logger class TestChatterTweaks(BaseFunctionalTest, TestRecipients): + @classmethod + def setUpClass(cls): + super(TestChatterTweaks, cls).setUpClass() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) + def test_post_no_subscribe_author(self): original = self.test_record.message_follower_ids self.test_record.with_user(self.user_employee).with_context({'mail_create_nosubscribe': True}).message_post( @@ -14,6 +19,7 @@ class TestChatterTweaks(BaseFunctionalTest, TestRecipients): self.assertEqual(self.test_record.message_follower_ids.mapped('partner_id'), original.mapped('partner_id')) self.assertEqual(self.test_record.message_follower_ids.mapped('channel_id'), original.mapped('channel_id')) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_post_no_subscribe_recipients(self): original = self.test_record.message_follower_ids self.test_record.with_user(self.user_employee).with_context({'mail_create_nosubscribe': True}).message_post( @@ -21,6 +27,7 @@ class TestChatterTweaks(BaseFunctionalTest, TestRecipients): self.assertEqual(self.test_record.message_follower_ids.mapped('partner_id'), original.mapped('partner_id')) self.assertEqual(self.test_record.message_follower_ids.mapped('channel_id'), original.mapped('channel_id')) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_post_subscribe_recipients(self): original = self.test_record.message_follower_ids self.test_record.with_user(self.user_employee).with_context({'mail_create_nosubscribe': True, 'mail_post_autofollow': True}).message_post( @@ -72,42 +79,23 @@ class TestChatterTweaks(BaseFunctionalTest, TestRecipients): self.assertEqual(len(rec.sudo().mapped('message_ids.tracking_value_ids')), 0, "Creation message without tracking values should have been posted") + def test_cache_invalidation(self): + """ Test that creating a mail-thread record does not invalidate the whole cache. """ + # make a new record in cache + record = self.env['res.partner'].new({'name': 'Brave New Partner'}) + self.assertTrue(record.name) -class TestNotifications(BaseFunctionalTest, MockEmails): + # creating a mail-thread record should not invalidate the whole cache + self.env['res.partner'].create({'name': 'Actual Partner'}) + self.assertTrue(record.name) - def setUp(self): - self.partner_1 = self.env['res.partner'].with_context(BaseFunctionalTest._test_context).create({ - 'name': 'Valid Lelitre', - 'email': 'valid.lelitre@agrolait.com'}) - (self.user_employee | self.user_admin).write({'notification_type': 'inbox'}) - super(TestNotifications, self).setUp() +class TestDiscuss(BaseFunctionalTest, TestRecipients, MockEmails): - def test_needaction(self): - with self.assertNotifications(partner_employee=(1, 'inbox', 'unread'), partner_admin=(0, '', '')): - self.test_record.message_post( - body='Test', message_type='comment', subtype='mail.mt_comment', - partner_ids=[self.user_employee.partner_id.id]) - - self.test_record.message_subscribe([self.partner_1.id]) - with self.assertNotifications(partner_employee=(1, 'inbox', 'unread'), partner_admin=(0, '', ''), partner_1=(1, 'email', 'read')): - self.test_record.message_post( - body='Test', message_type='comment', subtype='mail.mt_comment', - partner_ids=[self.user_employee.partner_id.id]) - - def test_inactive_follower(self): - # In some case odoobot is follower of a record. - # Even if it shouldn't be the case, we want to be sure that odoobot is not notified - self.test_record._message_subscribe(self.user_employee.partner_id.ids) - with self.assertNotifications(partner_employee=(1, 'inbox', 'unread')): - self.test_record.message_post( - body='Test', message_type='comment', subtype='mail.mt_comment') - self.user_employee.active = False - # at this point, partner is still active and would receive an email notification - self.user_employee.partner_id._write({'active': False}) - with self.assertNotifications(partner_employee=(0, '', '')): - self.test_record.message_post( - body='Test', message_type='comment', subtype='mail.mt_comment') + @classmethod + def setUpClass(cls): + super(TestDiscuss, cls).setUpClass() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) def test_set_message_done_user(self): with self.assertNotifications(partner_employee=(0, '', '')): @@ -116,16 +104,6 @@ class TestNotifications(BaseFunctionalTest, MockEmails): partner_ids=[self.user_employee.partner_id.id]) message.with_user(self.user_employee).set_message_done() - def test_set_message_done_portal(self): - user_portal = mail_new_test_user(self.env, login='chell', groups='base.group_portal', name='Chell Gladys', notification_type='inbox') - self.partner_portal = user_portal.partner_id - - with self.assertNotifications(partner_employee=(1, 'inbox', 'unread'), partner_portal=(1, 'inbox', 'read')): - message = self.test_record.message_post( - body='Test', message_type='comment', subtype='mail.mt_comment', - partner_ids=[self.user_employee.partner_id.id, user_portal.partner_id.id]) - message.with_user(user_portal).set_message_done() - def test_set_star(self): msg = self.test_record.with_user(self.user_admin).message_post(body='My Body', subject='1') msg_emp = self.env['mail.message'].with_user(self.user_employee).browse(msg.id) @@ -143,19 +121,12 @@ class TestNotifications(BaseFunctionalTest, MockEmails): self.assertFalse(msg.starred) self.assertTrue(msg_emp.starred) - -class TestChatterMisc(BaseFunctionalTest): - - def test_alias_setup(self): - alias = self.env['mail.alias'].with_context(alias_model_name='mail.test').create({'alias_name': 'b4r+_#_R3wl$$'}) - self.assertEqual(alias.alias_name, 'b4r+_-_r3wl-', 'Disallowed chars should be replaced by hyphens') - - def test_cache_invalidation(self): - """ Test that creating a mail-thread record does not invalidate the whole cache. """ - # make a new record in cache - record = self.env['res.partner'].new({'name': 'Brave New Partner'}) - self.assertTrue(record.name) - - # creating a mail-thread record should not invalidate the whole cache - self.env['res.partner'].create({'name': 'Actual Partner'}) - self.assertTrue(record.name) + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mail_cc_recipient_suggestion(self): + record = self.env['mail.test.cc'].create({'email_cc': 'cc1@example.com, cc2@example.com, cc3Dear ${object.name}, your parent is ${object.parent_id and object.parent_id.name or "False"}
', - }) + email_template = self._create_template('res.partner', {'partner_to': '%s' % self.test_partner.id}) self.action.write({'state': 'email', 'template_id': email_template.id}) self.action.with_context(self.context).run() # check an email is waiting for sending mail = self.env['mail.mail'].search([('subject', '=', 'About TestingPartner')]) self.assertEqual(len(mail), 1) # check email content - self.assertEqual(mail.body, 'Dear TestingPartner, your parent is False
') + self.assertEqual(mail.body, 'Hello TestingPartner
') def test_action_followers(self): self.test_partner.message_unsubscribe(self.test_partner.message_partner_ids.ids) diff --git a/addons/test_mail/tests/test_mail_activity.py b/addons/test_mail/tests/test_mail_activity.py index cb7d913a7e4..f72940b07a5 100644 --- a/addons/test_mail/tests/test_mail_activity.py +++ b/addons/test_mail/tests/test_mail_activity.py @@ -10,8 +10,8 @@ import pytz from odoo import exceptions, tests from odoo.addons.test_mail.tests.common import BaseFunctionalTest -from odoo.addons.test_mail.tests.common import mail_new_test_user from odoo.addons.test_mail.models.test_mail_models import MailTestActivity +from odoo.tools import mute_logger class TestActivityCommon(BaseFunctionalTest): @@ -19,7 +19,7 @@ class TestActivityCommon(BaseFunctionalTest): @classmethod def setUpClass(cls): super(TestActivityCommon, cls).setUpClass() - cls.test_record = cls.env['mail.test.activity'].with_context(BaseFunctionalTest._test_context).create({'name': 'Test'}) + cls.test_record = cls.env['mail.test.activity'].with_context(cls._test_context).create({'name': 'Test'}) # reset ctx cls.test_record = cls.test_record.with_context( mail_create_nolog=False, @@ -31,6 +31,7 @@ class TestActivityCommon(BaseFunctionalTest): @tests.tagged('mail_activity') class TestActivityRights(TestActivityCommon): + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_security_user_access_other(self): activity = self.test_record.with_user(self.user_employee).activity_schedule( 'test_mail.mail_act_test_todo', @@ -38,12 +39,14 @@ class TestActivityRights(TestActivityCommon): self.assertTrue(activity.can_write) activity.write({'user_id': self.user_employee.id}) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_security_user_access_own(self): activity = self.test_record.with_user(self.user_employee).activity_schedule( 'test_mail.mail_act_test_todo') self.assertTrue(activity.can_write) activity.write({'user_id': self.user_admin.id}) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_security_user_noaccess_automated(self): def _employee_crash(*args, **kwargs): """ If employee is test employee, consider he has no access on document """ @@ -90,7 +93,7 @@ class TestActivityRights(TestActivityCommon): class TestActivityFlow(TestActivityCommon): def test_activity_flow_employee(self): - with self.sudo('ernest'): + with self.sudo('employee'): test_record = self.env['mail.test.activity'].browse(self.test_record.id) self.assertEqual(test_record.activity_ids, self.env['mail.activity']) @@ -118,19 +121,7 @@ class TestActivityFlow(TestActivityCommon): self.assertEqual(test_record.activity_ids, self.env['mail.activity']) self.assertEqual(test_record.message_ids[0].subtype_id, self.env.ref('mail.mt_activities')) - def test_activity_flow_portal(self): - portal_user = mail_new_test_user(self.env, login='chell', groups='base.group_portal', name='Chell Gladys') - - with self.sudo('chell'): - test_record = self.env['mail.test.activity'].browse(self.test_record.id) - with self.assertRaises(exceptions.AccessError): - self.env['mail.activity'].create({ - 'summary': 'Test Activity', - 'activity_type_id': self.env.ref('mail.mail_activity_data_email').id, - 'res_model_id': self.env['ir.model']._get(test_record._name).id, - 'res_id': test_record.id, - }) - + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_notify_other_user(self): self.user_admin.notification_type = 'email' rec = self.test_record.with_user(self.user_employee) @@ -151,6 +142,7 @@ class TestActivityFlow(TestActivityCommon): self.assertEqual(activity.create_uid, self.user_employee) self.assertEqual(activity.user_id, self.user_employee) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_dont_notify_no_user_change(self): self.user_employee.notification_type = 'email' activity = self.test_record.activity_schedule('test_mail.mail_act_test_todo', user_id=self.user_employee.id) @@ -162,9 +154,10 @@ class TestActivityFlow(TestActivityCommon): @tests.tagged('mail_activity') class TestActivityMixin(TestActivityCommon): + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_mixin(self): self.user_employee.tz = self.user_admin.tz - with self.sudo('ernest'): + with self.sudo('employee'): self.test_record = self.env['mail.test.activity'].browse(self.test_record.id) self.assertEqual(self.test_record.env.user, self.user_employee) @@ -242,6 +235,7 @@ class TestActivityMixin(TestActivityCommon): self.assertEqual(self.test_record.activity_ids, self.env['mail.activity']) self.assertEqual(len(self.test_record.message_ids), 2) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_mixin_archive(self): rec = self.test_record.with_user(self.user_employee) new_act = rec.activity_schedule( @@ -255,6 +249,7 @@ class TestActivityMixin(TestActivityCommon): self.assertEqual(rec.active, True) self.assertEqual(rec.activity_ids, self.env['mail.activity']) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_mixin_reschedule_user(self): rec = self.test_record.with_user(self.user_employee) rec.activity_schedule( diff --git a/addons/test_mail/tests/test_mail_cc.py b/addons/test_mail/tests/test_mail_cc.py deleted file mode 100644 index 45503d3b649..00000000000 --- a/addons/test_mail/tests/test_mail_cc.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from odoo.addons.test_mail.tests import common -from odoo.tests import tagged -from odoo.tools import mute_logger, email_split_and_format -from odoo.addons.test_mail.data.test_mail_data import MAIL_TEMPLATE - - -@tagged('mail_thread_cc') -class TestMailCc(common.BaseFunctionalTest, common.MockEmails): - - @classmethod - def setUpClass(cls): - super(TestMailCc, cls).setUpClass() - - cls.email_from = 'Sylvie LelitreTest
', + 'notification': True, + 'state': 'outgoing', + 'recipient_ids': [(4, self.partner.id)] + }) + message = self.env['mail.message'].create({ + 'subject': 'S', + 'body': 'B', + 'subtype_id': self.ref('mail.mt_comment'), + 'notification_ids': [(0, 0, { + 'res_partner_id': self.partner.id, + 'mail_id': mail.id, + 'notification_type': 'email', + 'is_read': True, + 'notification_status': 'ready', + })], + }) + notif = self.env['mail.notification'].search([('res_partner_id', '=', self.partner.id)]) + # we need to commit transaction or cr will keep the lock on notif + self.cr.commit() + + # patch send_email in order to create a concurent update and check the notif is already locked by _send() + this = self # coding in javascript ruinned my life + bounce_deferred = [] + @api.model + def send_email(self, message, *args, **kwargs): + with this.registry.cursor() as cr, mute_logger('odoo.sql_db'): + try: + # try ro aquire lock (no wait) on notification (should fail) + cr.execute("SELECT notification_status FROM mail_message_res_partner_needaction_rel WHERE id = %s FOR UPDATE NOWAIT", [notif.id]) + except psycopg2.OperationalError: + # record already locked by send, all good + bounce_deferred.append(True) + else: + # this should trigger psycopg2.extensions.TransactionRollbackError in send(). + # Only here to simulate the initial use case + # If the record is lock, this line would create a deadlock since we are in the same thread + # In practice, the update will wait the end of the send() transaction and set the notif as bounce, as expeced + cr.execute("UPDATE mail_message_res_partner_needaction_rel SET notification_status='bounce' WHERE id = %s", [notif.id]) + return message['Message-Id'] + self.env['ir.mail_server']._patch_method('send_email', send_email) + + mail.send() + + self.assertTrue(bounce_deferred, "The bounce should have been deferred") + self.assertEqual(notif.notification_status, 'sent') + + # some cleaning since we commited the cr + notif.unlink() + message.unlink() + mail.unlink() + self.partner.unlink() + self.env.cr.commit() diff --git a/addons/test_mail/tests/test_mail_message.py b/addons/test_mail/tests/test_mail_message.py index d4181f5b334..6d3290a8a95 100644 --- a/addons/test_mail/tests/test_mail_message.py +++ b/addons/test_mail/tests/test_mail_message.py @@ -16,17 +16,16 @@ class TestMessageValues(common.BaseFunctionalTest, common.MockEmails): def setUpClass(cls): super(TestMessageValues, cls).setUpClass() - cls.alias_record = cls.env['mail.test'].with_context(common.BaseFunctionalTest._test_context).create({ + cls._init_mail_gateway() + cls.alias_record = cls.env['mail.test'].with_context(cls._test_context).create({ 'name': 'Pigs', 'alias_name': 'pigs', 'alias_contact': 'followers', }) - cls.Message = cls.env['mail.message'].with_user(cls.user_employee) - def test_mail_message_values_basic(self): - self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.domain')]).unlink() - + @mute_logger('odoo.models.unlink') + def test_mail_message_values_no_document_values(self): msg = self.Message.create({ 'reply_to': 'test.reply@example.com', 'email_from': 'test.from@example.com', @@ -35,39 +34,45 @@ class TestMessageValues(common.BaseFunctionalTest, common.MockEmails): self.assertEqual(msg.reply_to, 'test.reply@example.com') self.assertEqual(msg.email_from, 'test.from@example.com') - def test_mail_message_values_default(self): - self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.domain')]).unlink() - - msg = self.Message.create({}) - self.assertIn('-private', msg.message_id.split('@')[0], 'mail_message: message_id for a void message should be a "private" one') - self.assertEqual(msg.reply_to, '%s <%s>' % (self.user_employee.name, self.user_employee.email)) - self.assertEqual(msg.email_from, '%s <%s>' % (self.user_employee.name, self.user_employee.email)) - @mute_logger('odoo.models.unlink') - def test_mail_message_values_alias(self): - alias_domain = 'example.com' - self.env['ir.config_parameter'].set_param('mail.catchall.domain', alias_domain) - self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.alias')]).unlink() - + def test_mail_message_values_no_document(self): msg = self.Message.create({}) self.assertIn('-private', msg.message_id.split('@')[0], 'mail_message: message_id for a void message should be a "private" one') - self.assertEqual(msg.reply_to, '%s <%s>' % (self.user_employee.name, self.user_employee.email)) - self.assertEqual(msg.email_from, '%s <%s>' % (self.user_employee.name, self.user_employee.email)) - - def test_mail_message_values_alias_catchall(self): - alias_domain = 'example.com' - alias_catchall = 'pokemon' - self.env['ir.config_parameter'].set_param('mail.catchall.domain', alias_domain) - self.env['ir.config_parameter'].set_param('mail.catchall.alias', alias_catchall) - - msg = self.Message.create({}) - self.assertIn('-private', msg.message_id.split('@')[0], 'mail_message: message_id for a void message should be a "private" one') - reply_to_name = self.env.company.name - reply_to_email = '%s@%s' % (alias_catchall, alias_domain) + reply_to_name = self.env.user.company_id.name + reply_to_email = '%s@%s' % (self.alias_catchall, self.alias_domain) self.assertEqual(msg.reply_to, formataddr((reply_to_name, reply_to_email))) self.assertEqual(msg.email_from, formataddr((self.user_employee.name, self.user_employee.email))) - def test_mail_message_values_document_no_alias(self): + # no alias domain -> author + self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.domain')]).unlink() + + msg = self.Message.create({}) + self.assertIn('-private', msg.message_id.split('@')[0], 'mail_message: message_id for a void message should be a "private" one') + self.assertEqual(msg.reply_to, formataddr((self.user_employee.name, self.user_employee.email))) + self.assertEqual(msg.email_from, formataddr((self.user_employee.name, self.user_employee.email))) + + # no alias catchall, no alias -> author + self.env['ir.config_parameter'].set_param('mail.catchall.domain', self.alias_domain) + self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.alias')]).unlink() + + msg = self.Message.create({}) + self.assertIn('-private', msg.message_id.split('@')[0], 'mail_message: message_id for a void message should be a "private" one') + self.assertEqual(msg.reply_to, formataddr((self.user_employee.name, self.user_employee.email))) + self.assertEqual(msg.email_from, formataddr((self.user_employee.name, self.user_employee.email))) + + @mute_logger('odoo.models.unlink') + def test_mail_message_values_document_alias(self): + msg = self.Message.create({ + 'model': 'mail.test', + 'res_id': self.alias_record.id + }) + self.assertIn('-openerp-%d-mail.test' % self.alias_record.id, msg.message_id.split('@')[0]) + reply_to_name = '%s %s' % (self.env.user.company_id.name, self.alias_record.name) + reply_to_email = '%s@%s' % (self.alias_record.alias_name, self.alias_domain) + self.assertEqual(msg.reply_to, formataddr((reply_to_name, reply_to_email))) + self.assertEqual(msg.email_from, '%s <%s>' % (self.user_employee.name, self.user_employee.email)) + + # no alias domain -> author self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.domain')]).unlink() msg = self.Message.create({ @@ -75,13 +80,11 @@ class TestMessageValues(common.BaseFunctionalTest, common.MockEmails): 'res_id': self.alias_record.id }) self.assertIn('-openerp-%d-mail.test' % self.alias_record.id, msg.message_id.split('@')[0]) - self.assertEqual(msg.reply_to, '%s <%s>' % (self.user_employee.name, self.user_employee.email)) - self.assertEqual(msg.email_from, '%s <%s>' % (self.user_employee.name, self.user_employee.email)) + self.assertEqual(msg.reply_to, formataddr((self.user_employee.name, self.user_employee.email))) + self.assertEqual(msg.email_from, formataddr((self.user_employee.name, self.user_employee.email))) - @mute_logger('odoo.models.unlink') - def test_mail_message_values_document_alias(self): - alias_domain = 'example.com' - self.env['ir.config_parameter'].set_param('mail.catchall.domain', alias_domain) + # no catchall -> don't care, alias + self.env['ir.config_parameter'].set_param('mail.catchall.domain', self.alias_domain) self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.alias')]).unlink() msg = self.Message.create({ @@ -90,25 +93,45 @@ class TestMessageValues(common.BaseFunctionalTest, common.MockEmails): }) self.assertIn('-openerp-%d-mail.test' % self.alias_record.id, msg.message_id.split('@')[0]) reply_to_name = '%s %s' % (self.env.company.name, self.alias_record.name) - reply_to_email = '%s@%s' % (self.alias_record.alias_name, alias_domain) + reply_to_email = '%s@%s' % (self.alias_record.alias_name, self.alias_domain) self.assertEqual(msg.reply_to, formataddr((reply_to_name, reply_to_email))) - self.assertEqual(msg.email_from, '%s <%s>' % (self.user_employee.name, self.user_employee.email)) + self.assertEqual(msg.email_from, formataddr((self.user_employee.name, self.user_employee.email))) - def test_mail_message_values_document_alias_catchall(self): - alias_domain = 'example.com' - alias_catchall = 'pokemon' - self.env['ir.config_parameter'].set_param('mail.catchall.domain', alias_domain) - self.env['ir.config_parameter'].set_param('mail.catchall.alias', alias_catchall) + @mute_logger('odoo.models.unlink') + def test_mail_message_values_document_no_alias(self): + test_record = self.env['mail.test.simple'].create({'name': 'Test', 'email_from': 'ignasse@example.com'}) msg = self.Message.create({ - 'model': 'mail.test', - 'res_id': self.alias_record.id + 'model': 'mail.test.simple', + 'res_id': test_record.id }) - self.assertIn('-openerp-%d-mail.test' % self.alias_record.id, msg.message_id.split('@')[0]) - reply_to_name = '%s %s' % (self.env.company.name, self.alias_record.name) - reply_to_email = '%s@%s' % (self.alias_record.alias_name, alias_domain) + self.assertIn('-openerp-%d-mail.test.simple' % test_record.id, msg.message_id.split('@')[0]) + reply_to_name = '%s %s' % (self.env.user.company_id.name, test_record.name) + reply_to_email = '%s@%s' % (self.alias_catchall, self.alias_domain) self.assertEqual(msg.reply_to, formataddr((reply_to_name, reply_to_email))) - self.assertEqual(msg.email_from, '%s <%s>' % (self.user_employee.name, self.user_employee.email)) + self.assertEqual(msg.email_from, formataddr((self.user_employee.name, self.user_employee.email))) + + @mute_logger('odoo.models.unlink') + def test_mail_message_values_document_manual_alias(self): + test_record = self.env['mail.test.simple'].create({'name': 'Test', 'email_from': 'ignasse@example.com'}) + alias = self.env['mail.alias'].create({ + 'alias_name': 'MegaLias', + 'alias_user_id': False, + 'alias_model_id': self.env['ir.model']._get('mail.test.simple').id, + 'alias_parent_model_id': self.env['ir.model']._get('mail.test.simple').id, + 'alias_parent_thread_id': test_record.id, + }) + + msg = self.Message.create({ + 'model': 'mail.test.simple', + 'res_id': test_record.id + }) + + self.assertIn('-openerp-%d-mail.test.simple' % test_record.id, msg.message_id.split('@')[0]) + reply_to_name = '%s %s' % (self.env.user.company_id.name, test_record.name) + reply_to_email = '%s@%s' % (alias.alias_name, self.alias_domain) + self.assertEqual(msg.reply_to, formataddr((reply_to_name, reply_to_email))) + self.assertEqual(msg.email_from, formataddr((self.user_employee.name, self.user_employee.email))) def test_mail_message_values_no_auto_thread(self): msg = self.Message.create({ @@ -139,7 +162,7 @@ class TestMessageAccess(common.BaseFunctionalTest, common.MockEmails): cls.user_public = mail_new_test_user(cls.env, login='bert', groups='base.group_public', name='Bert Tartignole') cls.user_portal = mail_new_test_user(cls.env, login='chell', groups='base.group_portal', name='Chell Gladys') - Channel = cls.env['mail.channel'].with_context(common.BaseFunctionalTest._test_context) + Channel = cls.env['mail.channel'].with_context(cls._test_context) # Pigs: base group for tests cls.group_pigs = Channel.create({ 'name': 'Pigs', diff --git a/addons/test_mail/tests/test_mail_race.py b/addons/test_mail/tests/test_mail_race.py deleted file mode 100644 index 310051a7d68..00000000000 --- a/addons/test_mail/tests/test_mail_race.py +++ /dev/null @@ -1,73 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -import psycopg2 - -from odoo import api -from odoo.addons.test_mail.tests import common as mail_common -from odoo.tests import common -from odoo.tools import mute_logger - - -class TestMailRace(common.TransactionCase, mail_common.MockEmails): - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_mail_bounce_during_send(self): - self.partner = self.env['res.partner'].create({ - 'name': 'Ernest Partner', - }) - # we need to simulate a mail sent by the cron task, first create mail, message and notification by hand - mail = self.env['mail.mail'].create({ - 'body_html': 'Test
', - 'notification': True, - 'state': 'outgoing', - 'recipient_ids': [(4, self.partner.id)] - }) - message = self.env['mail.message'].create({ - 'subject': 'S', - 'body': 'B', - 'subtype_id': self.ref('mail.mt_comment'), - 'notification_ids': [(0, 0, { - 'res_partner_id': self.partner.id, - 'mail_id': mail.id, - 'notification_type': 'email', - 'is_read': True, - 'notification_status': 'ready', - })], - }) - notif = self.env['mail.notification'].search([('res_partner_id', '=', self.partner.id)]) - # we need to commit transaction or cr will keep the lock on notif - self.cr.commit() - - # patch send_email in order to create a concurent update and check the notif is already locked by _send() - this = self # coding in javascript ruinned my life - bounce_deferred = [] - @api.model - def send_email(self, message, *args, **kwargs): - with this.registry.cursor() as cr, mute_logger('odoo.sql_db'): - try: - # try ro aquire lock (no wait) on notification (should fail) - cr.execute("SELECT notification_status FROM mail_message_res_partner_needaction_rel WHERE id = %s FOR UPDATE NOWAIT", [notif.id]) - except psycopg2.OperationalError: - # record already locked by send, all good - bounce_deferred.append(True) - else: - # this should trigger psycopg2.extensions.TransactionRollbackError in send(). - # Only here to simulate the initial use case - # If the record is lock, this line would create a deadlock since we are in the same thread - # In practice, the update will wait the end of the send() transaction and set the notif as bounce, as expeced - cr.execute("UPDATE mail_message_res_partner_needaction_rel SET notification_status='bounce' WHERE id = %s", [notif.id]) - return message['Message-Id'] - self.env['ir.mail_server']._patch_method('send_email', send_email) - - mail.send() - - self.assertTrue(bounce_deferred, "The bounce should have been deferred") - self.assertEqual(notif.notification_status, 'sent') - - # some cleaning since we commited the cr - notif.unlink() - message.unlink() - mail.unlink() - self.partner.unlink() - self.env.cr.commit() diff --git a/addons/test_mail/tests/test_multi_company.py b/addons/test_mail/tests/test_mail_redirect.py similarity index 100% rename from addons/test_mail/tests/test_multi_company.py rename to addons/test_mail/tests/test_mail_redirect.py diff --git a/addons/test_mail/tests/test_mail_template.py b/addons/test_mail/tests/test_mail_template.py index df3f47b4d95..5ef9d8277a2 100644 --- a/addons/test_mail/tests/test_mail_template.py +++ b/addons/test_mail/tests/test_mail_template.py @@ -2,191 +2,54 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. import base64 -from datetime import datetime, timedelta -from unittest.mock import patch from odoo.addons.test_mail.tests.common import BaseFunctionalTest, MockEmails, TestRecipients -from odoo.addons.test_mail.tests.common import mail_new_test_user -from odoo.tools import mute_logger, DEFAULT_SERVER_DATETIME_FORMAT +from odoo.tools import mute_logger class TestMailTemplate(BaseFunctionalTest, MockEmails, TestRecipients): - def setUp(self): - super(TestMailTemplate, self).setUp() + @classmethod + def setUpClass(cls): + super(TestMailTemplate, cls).setUpClass() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) - self.user_employee.write({ - 'groups_id': [(4, self.env.ref('base.group_partner_manager').id)], + cls.user_employee.write({ + 'groups_id': [(4, cls.env.ref('base.group_partner_manager').id)], }) - self._attachments = [{ + cls._attachments = [{ 'name': 'first.txt', 'datas': base64.b64encode(b'My first attachment'), 'res_model': 'res.partner', - 'res_id': self.user_admin.partner_id.id + 'res_id': cls.user_admin.partner_id.id }, { 'name': 'second.txt', 'datas': base64.b64encode(b'My second attachment'), 'res_model': 'res.partner', - 'res_id': self.user_admin.partner_id.id + 'res_id': cls.user_admin.partner_id.id }] - self.email_1 = 'test1@example.com' - self.email_2 = 'test2@example.com' - self.email_3 = self.partner_1.email - self.email_template = self.env['mail.template'].create({ - 'model_id': self.env['ir.model']._get('mail.test.simple').id, - 'name': 'Pigs Template', - 'subject': '${object.name}', - 'body_html': '${object.email_from}', - 'user_signature': False, - 'attachment_ids': [(0, 0, self._attachments[0]), (0, 0, self._attachments[1])], - 'partner_to': '%s,%s' % (self.partner_2.id, self.user_admin.partner_id.id), - 'email_to': '%s, %s' % (self.email_1, self.email_2), - 'email_cc': '%s' % self.email_3}) + cls.email_1 = 'test1@example.com' + cls.email_2 = 'test2@example.com' + cls.email_3 = cls.partner_1.email + cls._create_template('mail.test.simple', { + 'attachment_ids': [(0, 0, cls._attachments[0]), (0, 0, cls._attachments[1])], + 'partner_to': '%s,%s' % (cls.partner_2.id, cls.user_admin.partner_id.id), + 'email_to': '%s, %s' % (cls.email_1, cls.email_2), + 'email_cc': '%s' % cls.email_3, + }) # admin should receive emails - self.user_admin.write({'notification_type': 'email'}) + cls.user_admin.write({'notification_type': 'email'}) # Force the attachments of the template to be in the natural order. - self.email_template.invalidate_cache(['attachment_ids'], ids=self.email_template.ids) - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_composer_w_template(self): - composer = self.env['mail.compose.message'].with_user(self.user_employee).with_context({ - 'default_composition_mode': 'comment', - 'default_model': 'mail.test.simple', - 'default_res_id': self.test_record.id, - 'default_template_id': self.email_template.id, - }).create({'subject': 'Forget me subject', 'body': 'Dummy body'}) - - # perform onchange and send emails - values = composer.onchange_template_id(self.email_template.id, 'comment', self.test_record._name, self.test_record.id)['value'] - composer.write(values) - composer.send_mail() - - new_partners = self.env['res.partner'].search([('email', 'in', [self.email_1, self.email_2])]) - self.assertEmails( - self.user_employee.partner_id, - [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], - subject=self.test_record.name, - body_content=self.test_record.email_from, - attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) - - def test_composer_template_onchange_attachments(self): - """Tests that all attachments are added to the composer, - static attachments are not duplicated and while reports are re-generated, - and that intermediary attachments are dropped.""" - - composer = self.env['mail.compose.message'].with_context(default_attachment_ids=[]).create({}) - report_template = self.env.ref('web.action_report_externalpreview') - template_1 = self.email_template.copy({ - 'report_template': report_template.id, - }) - template_2 = self.email_template.copy({ - 'attachment_ids': False, - 'report_template': report_template.id, - }) - - onchange_templates = [template_1, template_2, template_1, False] - attachments_onchange = [composer.attachment_ids] - # template_1 has two static attachments and one dynamically generated report, - # template_2 only has the report, so we should get 3, 1, 3 attachments - attachment_numbers = [0, 3, 1, 3, 0] - - for template in onchange_templates: - onchange = composer.onchange_template_id( - template.id if template else False, 'comment', self.test_record._name, self.test_record.id - ) - composer.update(onchange['value']) - attachments_onchange.append(composer.attachment_ids) - - self.assertEqual( - [len(attachments) for attachments in attachments_onchange], - attachment_numbers, - ) - - self.assertTrue( - len(attachments_onchange[1] & attachments_onchange[3]) == 2, - "The two static attachments on the template should be common to the two onchanges" - ) - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_post_post_w_template(self): - self.test_record.with_user(self.user_employee).message_post_with_template(self.email_template.id, composition_mode='comment') - - new_partners = self.env['res.partner'].search([('email', 'in', [self.email_1, self.email_2])]) - self.assertEmails( - self.user_employee.partner_id, - [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], - subject=self.test_record.name, - body_content=self.test_record.email_from, - attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_composer_w_template_mass_mailing(self): - test_record_2 = self.env['mail.test.simple'].with_context(BaseFunctionalTest._test_context).create({'name': 'Test2', 'email_from': 'laurie.poiret@example.com'}) - - composer = self.env['mail.compose.message'].with_user(self.user_employee).with_context({ - 'default_composition_mode': 'mass_mail', - # 'default_notify': True, - 'default_notify': False, - 'default_model': 'mail.test.simple', - 'default_res_id': self.test_record.id, - 'default_template_id': self.email_template.id, - 'active_ids': [self.test_record.id, test_record_2.id] - }).create({}) - values = composer.onchange_template_id(self.email_template.id, 'mass_mail', 'mail.test.simple', self.test_record.id)['value'] - composer.write(values) - composer.send_mail() - - new_partners = self.env['res.partner'].search([('email', 'in', [self.email_1, self.email_2])]) - # hack to use assertEmails - self._mails_record1 = [dict(mail) for mail in self._mails if '%s-%s' % (self.test_record.id, self.test_record._name) in mail['message_id']] - self._mails_record2 = [dict(mail) for mail in self._mails if '%s-%s' % (test_record_2.id, test_record_2._name) in mail['message_id']] - - self._mails = self._mails_record1 - self.assertEmails( - self.user_employee.partner_id, - [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], - subject=self.test_record.name, - body_content=self.test_record.email_from, - attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) - - self._mails = self._mails_record2 - self.assertEmails( - self.user_employee.partner_id, - [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], - subject=test_record_2.name, - body_content=test_record_2.email_from, - attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) - - message_1 = self.test_record.message_ids[0] - message_2 = test_record_2.message_ids[0] - - # messages effectively posted - self.assertEqual(message_1.subject, self.test_record.name) - self.assertEqual(message_2.subject, test_record_2.name) - self.assertIn(self.test_record.email_from, message_1.body) - self.assertIn(test_record_2.email_from, message_2.body) - - def test_composer_template_save(self): - self.env['mail.compose.message'].with_context({ - 'default_composition_mode': 'comment', - 'default_model': 'mail.test.simple', - 'default_res_id': self.test_record.id, - }).create({ - 'subject': 'Forget me subject', - 'body': 'Dummy body
' - }).save_as_template() - # Test: email_template subject, body_html, model - last_template = self.env['mail.template'].search([('model', '=', 'mail.test.simple'), ('subject', '=', 'Forget me subject')], limit=1) - self.assertEqual(last_template.body_html, 'Dummy body
', 'email_template incorrect body_html') + cls.email_template.invalidate_cache(['attachment_ids'], ids=cls.email_template.ids) @mute_logger('odoo.addons.mail.models.mail_mail') def test_template_send_email(self): mail_id = self.email_template.send_mail(self.test_record.id) mail = self.env['mail.mail'].browse(mail_id) - self.assertEqual(mail.subject, self.test_record.name) + self.assertEqual(mail.subject, 'About %s' % self.test_record.name) self.assertEqual(mail.email_to, self.email_template.email_to) self.assertEqual(mail.email_cc, self.email_template.email_cc) self.assertEqual(mail.recipient_ids, self.partner_2 | self.user_admin.partner_id) @@ -241,37 +104,3 @@ class TestMailTemplate(BaseFunctionalTest, MockEmails, TestRecipients): # self.env['mail.mail'].process_email_queue(ids=[mail_in_2_days.id]) # self.assertEqual(mail_in_2_days.state, 'outgoing') # self.assertEqual(mail_now.exists() | mail_in_2_days.exists(), mail_in_2_days) - - def test_create_partner_from_tracking_multicompany(self): - company1 = self.env['res.company'].create({'name': 'company1'}) - self.env.user.write({'company_ids': [(4, company1.id, False)]}) - self.assertNotEqual(self.env.company, company1) - - email_new_partner = "diamonds@rust.com" - Partner = self.env['res.partner'] - self.assertFalse(Partner.search([('email', '=', email_new_partner)])) - - template = self.env['mail.template'].create({ - 'model_id': self.env['ir.model']._get('mail.test.track').id, - 'name': 'AutoTemplate', - 'subject': 'autoresponse', - 'email_from': self.env.user.email_formatted, - 'email_to': "${object.email_from}", - 'body_html': "Test Body
', + 'partner_ids': [(4, self.partner_1.id), (4, self.partner_2.id)] + }) + composer.send_mail() + + message = self.test_record.message_ids[0] + self.assertEqual(message.body, 'Test Body
') + self.assertEqual(message.author_id, self.user_employee.partner_id) + self.assertEqual(message.subject, 'Re: %s' % self.test_record.name) + self.assertEqual(message.subtype_id, self.env.ref('mail.mt_comment')) + self.assertEqual(message.partner_ids, self.partner_1 | self.partner_2) + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_composer_comment_parent(self): + parent = self.test_record.message_post(body='Test') + + self.env['mail.compose.message'].with_context({ + 'default_composition_mode': 'comment', + 'default_parent_id': parent.id + }).with_user(self.user_employee).create({ + 'body': 'Mega
', + }).send_mail() + + message = self.test_record.message_ids[0] + self.assertEqual(message.body, 'Mega
') + self.assertEqual(message.parent_id, parent) + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_composer_mass_mail(self): + test_record_2 = self.env['mail.test.simple'].with_context(self._test_context).create({'name': 'Test2'}) + + composer = self.env['mail.compose.message'].with_context({ + 'default_composition_mode': 'mass_mail', + 'default_model': self.test_record._name, + 'default_res_id': False, + 'active_ids': [self.test_record.id, test_record_2.id] + }).with_user(self.user_employee).create({ + 'subject': 'Testing ${object.name}', + 'body': '${object.name}
', + 'partner_ids': [(4, self.partner_1.id), (4, self.partner_2.id)] + }) + composer.with_context({ + 'default_res_id': -1, + 'active_ids': [self.test_record.id, test_record_2.id] + }).send_mail() + + # check mail_mail + mails = self.env['mail.mail'].search([('subject', 'ilike', 'Testing')]) + for mail in mails: + self.assertEqual(mail.recipient_ids, self.partner_1 | self.partner_2, + 'compose wizard: mail_mail mass mailing: mail.mail in mass mail incorrect recipients') + + # check message on test_record + message1 = self.test_record.message_ids[0] + self.assertEqual(message1.subject, 'Testing %s' % self.test_record.name) + self.assertEqual(message1.body, '%s
' % self.test_record.name) + + # check message on test_record_2 + message1 = test_record_2.message_ids[0] + self.assertEqual(message1.subject, 'Testing %s' % test_record_2.name) + self.assertEqual(message1.body, '%s
' % test_record_2.name) + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_composer_mass_mail_active_domain(self): + test_record_2 = self.env['mail.test.simple'].with_context(self._test_context).create({'name': 'Test2'}) + + self.env['mail.compose.message'].with_context({ + 'default_composition_mode': 'mass_mail', + 'default_model': self.test_record._name, + 'default_use_active_domain': True, + 'active_ids': [self.test_record.id], + 'active_domain': [('name', 'in', ['%s' % self.test_record.name, '%s' % test_record_2.name])], + }).with_user(self.user_employee).create({ + 'subject': 'From Composer Test', + 'body': '${object.name}', + }).send_mail() + + self.assertEqual(self.test_record.message_ids[0].subject, 'From Composer Test') + self.assertEqual(test_record_2.message_ids[0].subject, 'From Composer Test') + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_message_compose_mass_mail_no_active_domain(self): + test_record_2 = self.env['mail.test.simple'].with_context(self._test_context).create({'name': 'Test2'}) + + self.env['mail.compose.message'].with_context({ + 'default_composition_mode': 'mass_mail', + 'default_model': self.test_record._name, + 'default_use_active_domain': False, + 'active_ids': [self.test_record.id], + 'active_domain': [('name', 'in', ['%s' % self.test_record.name, '%s' % test_record_2.name])], + }).with_user(self.user_employee).create({ + 'subject': 'From Composer Test', + 'body': '${object.name}', + }).send_mail() + + self.assertEqual(self.test_record.message_ids[0].subject, 'From Composer Test') + self.assertFalse(test_record_2.message_ids.ids) + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_message_compose_portal_ok(self): + portal_user = mail_new_test_user(self.env, login='chell', groups='base.group_portal', name='Chell Gladys') + + with patch.object(MailTestSimple, 'check_access_rights', return_value=True): + ComposerPortal = self.env['mail.compose.message'].with_user(portal_user) + + ComposerPortal.with_context({ + 'default_composition_mode': 'comment', + 'default_model': self.test_record._name, + 'default_res_id': self.test_record.id, + }).create({ + 'subject': 'Subject', + 'body': 'Body text
', + 'partner_ids': []}).send_mail() + + self.assertEqual(self.test_record.message_ids[0].body, 'Body text
') + self.assertEqual(self.test_record.message_ids[0].author_id, portal_user.partner_id) + + ComposerPortal.with_context({ + 'default_composition_mode': 'comment', + 'default_parent_id': self.test_record.message_ids.ids[0], + }).create({ + 'subject': 'Subject', + 'body': 'Body text 2
'}).send_mail() + + self.assertEqual(self.test_record.message_ids[0].body, 'Body text 2
') + self.assertEqual(self.test_record.message_ids[0].author_id, portal_user.partner_id) + + +class TestComposerWTpl(BaseFunctionalTest, MockEmails, TestRecipients): + + @classmethod + def setUpClass(cls): + super(TestComposerWTpl, cls).setUpClass() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) + + cls.user_employee.write({ + 'groups_id': [(4, cls.env.ref('base.group_partner_manager').id)], + }) + + cls._attachments = [{ + 'name': 'first.txt', + 'datas': base64.b64encode(b'My first attachment'), + 'res_model': 'res.partner', + 'res_id': cls.user_admin.partner_id.id + }, { + 'name': 'second.txt', + 'datas': base64.b64encode(b'My second attachment'), + 'res_model': 'res.partner', + 'res_id': cls.user_admin.partner_id.id + }] + + cls.email_1 = 'test1@example.com' + cls.email_2 = 'test2@example.com' + cls.email_3 = cls.partner_1.email + cls._create_template('mail.test.simple', { + 'attachment_ids': [(0, 0, cls._attachments[0]), (0, 0, cls._attachments[1])], + 'partner_to': '%s,%s' % (cls.partner_2.id, cls.user_admin.partner_id.id), + 'email_to': '%s, %s' % (cls.email_1, cls.email_2), + 'email_cc': '%s' % cls.email_3, + }) + + # admin should receive emails + cls.user_admin.write({'notification_type': 'email'}) + # Force the attachments of the template to be in the natural order. + cls.email_template.invalidate_cache(['attachment_ids'], ids=cls.email_template.ids) + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_composer_w_template(self): + composer = self.env['mail.compose.message'].with_user(self.user_employee).with_context({ + 'default_composition_mode': 'comment', + 'default_model': 'mail.test.simple', + 'default_res_id': self.test_record.id, + 'default_template_id': self.email_template.id, + }).create({'subject': 'Forget me subject', 'body': 'Dummy body'}) + + # perform onchange and send emails + values = composer.onchange_template_id(self.email_template.id, 'comment', self.test_record._name, self.test_record.id)['value'] + composer.write(values) + composer.send_mail() + + new_partners = self.env['res.partner'].search([('email', 'in', [self.email_1, self.email_2])]) + self.assertEmails( + self.user_employee.partner_id, + [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], + subject='About %s' % self.test_record.name, + body_content=self.test_record.name, + attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) + + def test_composer_template_onchange_attachments(self): + """Tests that all attachments are added to the composer, + static attachments are not duplicated and while reports are re-generated, + and that intermediary attachments are dropped.""" + + composer = self.env['mail.compose.message'].with_context(default_attachment_ids=[]).create({}) + report_template = self.env.ref('web.action_report_externalpreview') + template_1 = self.email_template.copy({ + 'report_template': report_template.id, + }) + template_2 = self.email_template.copy({ + 'attachment_ids': False, + 'report_template': report_template.id, + }) + + onchange_templates = [template_1, template_2, template_1, False] + attachments_onchange = [composer.attachment_ids] + # template_1 has two static attachments and one dynamically generated report, + # template_2 only has the report, so we should get 3, 1, 3 attachments + attachment_numbers = [0, 3, 1, 3, 0] + + for template in onchange_templates: + onchange = composer.onchange_template_id( + template.id if template else False, 'comment', self.test_record._name, self.test_record.id + ) + composer.update(onchange['value']) + attachments_onchange.append(composer.attachment_ids) + + self.assertEqual( + [len(attachments) for attachments in attachments_onchange], + attachment_numbers, + ) + + self.assertTrue( + len(attachments_onchange[1] & attachments_onchange[3]) == 2, + "The two static attachments on the template should be common to the two onchanges" + ) + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_composer_w_template_mass_mailing(self): + test_record_2 = self.env['mail.test.simple'].with_context(self._test_context).create({'name': 'Test2', 'email_from': 'laurie.poiret@example.com'}) + + composer = self.env['mail.compose.message'].with_user(self.user_employee).with_context({ + 'default_composition_mode': 'mass_mail', + # 'default_notify': True, + 'default_notify': False, + 'default_model': 'mail.test.simple', + 'default_res_id': self.test_record.id, + 'default_template_id': self.email_template.id, + 'active_ids': [self.test_record.id, test_record_2.id] + }).create({}) + values = composer.onchange_template_id(self.email_template.id, 'mass_mail', 'mail.test.simple', self.test_record.id)['value'] + composer.write(values) + composer.send_mail() + + new_partners = self.env['res.partner'].search([('email', 'in', [self.email_1, self.email_2])]) + # hack to use assertEmails + self._mails_record1 = [dict(mail) for mail in self._mails if '%s-%s' % (self.test_record.id, self.test_record._name) in mail['message_id']] + self._mails_record2 = [dict(mail) for mail in self._mails if '%s-%s' % (test_record_2.id, test_record_2._name) in mail['message_id']] + + self._mails = self._mails_record1 + self.assertEmails( + self.user_employee.partner_id, + [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], + subject='About %s' % self.test_record.name, + body_content=self.test_record.name, + attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) + + self._mails = self._mails_record2 + self.assertEmails( + self.user_employee.partner_id, + [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], + subject='About %s' % test_record_2.name, + body_content=test_record_2.name, + attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) + + message_1 = self.test_record.message_ids[0] + message_2 = test_record_2.message_ids[0] + + # messages effectively posted + self.assertEqual(message_1.subject, 'About %s' % self.test_record.name) + self.assertEqual(message_2.subject, 'About %s' % test_record_2.name) + self.assertIn(self.test_record.name, message_1.body) + self.assertIn(test_record_2.name, message_2.body) + + def test_composer_template_save(self): + self.env['mail.compose.message'].with_context({ + 'default_composition_mode': 'comment', + 'default_model': 'mail.test.simple', + 'default_res_id': self.test_record.id, + }).create({ + 'subject': 'Forget me subject', + 'body': 'Dummy body
' + }).save_as_template() + # Test: email_template subject, body_html, model + last_template = self.env['mail.template'].search([('model', '=', 'mail.test.simple'), ('subject', '=', 'Forget me subject')], limit=1) + self.assertEqual(last_template.body_html, 'Dummy body
', 'email_template incorrect body_html') diff --git a/addons/test_mail/tests/test_mail_resend.py b/addons/test_mail/tests/test_message_management.py similarity index 94% rename from addons/test_mail/tests/test_mail_resend.py rename to addons/test_mail/tests/test_message_management.py index cec04958a9a..557eebd4ca7 100644 --- a/addons/test_mail/tests/test_mail_resend.py +++ b/addons/test_mail/tests/test_message_management.py @@ -17,15 +17,17 @@ class TestMailResend(common.BaseFunctionalTest, common.MockEmails): @classmethod def setUpClass(cls): super(TestMailResend, cls).setUpClass() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) + #Two users cls.user1 = mail_new_test_user(cls.env, login='e1', groups='base.group_public', name='Employee 1', email='e1') # invalid email cls.user2 = mail_new_test_user(cls.env, login='e2', groups='base.group_portal', name='Employee 2', email='e2@example.com') #Two partner - cls.partner1 = cls.env['res.partner'].with_context(common.BaseFunctionalTest._test_context).create({ + cls.partner1 = cls.env['res.partner'].with_context(cls._test_context).create({ 'name': 'Partner 1', 'email': 'p1' # invalid email }) - cls.partner2 = cls.env['res.partner'].with_context(common.BaseFunctionalTest._test_context).create({ + cls.partner2 = cls.env['res.partner'].with_context(cls._test_context).create({ 'name': 'Partner 2', 'email': 'p2@example.com' }) diff --git a/addons/test_mail/tests/test_message_compose.py b/addons/test_mail/tests/test_message_post.py similarity index 57% rename from addons/test_mail/tests/test_message_compose.py rename to addons/test_mail/tests/test_message_post.py index adf1dd80ae6..2eecfb98b9e 100644 --- a/addons/test_mail/tests/test_message_compose.py +++ b/addons/test_mail/tests/test_message_post.py @@ -7,26 +7,61 @@ from email.utils import formataddr from unittest.mock import patch from odoo.addons.test_mail.tests.common import BaseFunctionalTest, MockEmails, TestRecipients -from odoo.addons.test_mail.tests.common import mail_new_test_user from odoo.addons.test_mail.data.test_mail_data import MAIL_TEMPLATE_PLAINTEXT from odoo.addons.test_mail.models.test_mail_models import MailTestSimple from odoo.exceptions import AccessError from odoo.tools import mute_logger -class TestMessagePost(BaseFunctionalTest, MockEmails, TestRecipients): +class TestMessagePost(BaseFunctionalTest, TestRecipients, MockEmails): - def setUp(self): - super(TestMessagePost, self).setUp() + @classmethod + def setUpClass(cls): + super(TestMessagePost, cls).setUpClass() + cls._create_portal_user() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) # configure mailing - self.alias_domain = 'schlouby.fr' - self.alias_catchall = 'test+catchall' - self.env['ir.config_parameter'].set_param('mail.catchall.domain', self.alias_domain) - self.env['ir.config_parameter'].set_param('mail.catchall.alias', self.alias_catchall) + cls.alias_domain = 'schlouby.fr' + cls.alias_catchall = 'test+catchall' + cls.env['ir.config_parameter'].set_param('mail.catchall.domain', cls.alias_domain) + cls.env['ir.config_parameter'].set_param('mail.catchall.alias', cls.alias_catchall) - # admin should not receive emails - self.user_admin.write({'notification_type': 'email'}) + cls.user_admin.write({'notification_type': 'email'}) + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_post_needaction(self): + (self.user_employee | self.user_admin).write({'notification_type': 'inbox'}) + with self.assertNotifications(partner_employee=(1, 'inbox', 'unread'), partner_admin=(0, '', '')): + self.test_record.message_post( + body='Test', message_type='comment', subtype='mail.mt_comment', + partner_ids=[self.user_employee.partner_id.id]) + + self.test_record.message_subscribe([self.partner_1.id]) + with self.assertNotifications(partner_employee=(1, 'inbox', 'unread'), partner_admin=(0, '', ''), partner_1=(1, 'email', 'read')): + self.test_record.message_post( + body='Test', message_type='comment', subtype='mail.mt_comment', + partner_ids=[self.user_employee.partner_id.id]) + + with self.assertNotifications(partner_admin=(0, '', ''), partner_1=(1, 'email', 'read'), partner_portal=(1, 'email', 'read')): + self.test_record.message_post( + body='Test', message_type='comment', subtype='mail.mt_comment', + partner_ids=[self.partner_portal.id]) + + def test_post_inactive_follower(self): + # In some case odoobot is follower of a record. + # Even if it shouldn't be the case, we want to be sure that odoobot is not notified + (self.user_employee | self.user_admin).write({'notification_type': 'inbox'}) + self.test_record._message_subscribe(self.user_employee.partner_id.ids) + with self.assertNotifications(partner_employee=(1, 'inbox', 'unread')): + self.test_record.message_post( + body='Test', message_type='comment', subtype='mail.mt_comment') + self.user_employee.active = False + # at this point, partner is still active and would receive an email notification + self.user_employee.partner_id._write({'active': False}) + with self.assertNotifications(partner_employee=(0, '', '')): + self.test_record.message_post( + body='Test', message_type='comment', subtype='mail.mt_comment') @mute_logger('odoo.addons.mail.models.mail_mail') def test_post_notifications(self): @@ -153,22 +188,18 @@ class TestMessagePost(BaseFunctionalTest, MockEmails, TestRecipients): @mute_logger('odoo.addons.mail.models.mail_mail') def test_post_portal_ok(self): - portal_user = mail_new_test_user(self.env, login='chell', groups='base.group_portal', name='Chell Gladys') - with patch.object(MailTestSimple, 'check_access_rights', return_value=True): self.test_record.message_subscribe((self.partner_1 | self.user_employee.partner_id).ids) - new_msg = self.test_record.with_user(portal_user).message_post( + new_msg = self.test_record.with_user(self.user_portal).message_post( body='Test
', subject='Subject', message_type='comment', subtype='mt_comment') self.assertEqual(new_msg.sudo().notified_partner_ids, (self.partner_1 | self.user_employee.partner_id)) - self.assertEmails(portal_user.partner_id, [[self.partner_1], [self.user_employee.partner_id]]) + self.assertEmails(self.user_portal.partner_id, [[self.partner_1], [self.user_employee.partner_id]]) def test_post_portal_crash(self): - portal_user = mail_new_test_user(self.env, login='chell', groups='base.group_portal', name='Chell Gladys') - with self.assertRaises(AccessError): - self.test_record.with_user(portal_user).message_post( + self.test_record.with_user(self.user_portal).message_post( body='Test
', subject='Subject', message_type='comment', subtype='mt_comment') @@ -220,151 +251,43 @@ class TestMessagePost(BaseFunctionalTest, MockEmails, TestRecipients): self.assertNotIn(new_notification, self.test_record.message_ids) # todo xdo add test message_notify on thread with followers and stuff - -class TestComposer(BaseFunctionalTest, MockEmails, TestRecipients): - - def setUp(self): - super(TestComposer, self).setUp() - - # configure mailing - self.alias_domain = 'schlouby.fr' - self.alias_catchall = 'test+catchall' - self.env['ir.config_parameter'].set_param('mail.catchall.domain', self.alias_domain) - self.env['ir.config_parameter'].set_param('mail.catchall.alias', self.alias_catchall) - - # admin should not receive emails + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_post_post_w_template(self): + test_record = self.env['mail.test.simple'].with_context(self._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) + self.user_employee.write({ + 'groups_id': [(4, self.env.ref('base.group_partner_manager').id)], + }) + _attachments = [{ + 'name': 'first.txt', + 'datas': base64.b64encode(b'My first attachment'), + 'res_model': 'res.partner', + 'res_id': self.user_admin.partner_id.id + }, { + 'name': 'second.txt', + 'datas': base64.b64encode(b'My second attachment'), + 'res_model': 'res.partner', + 'res_id': self.user_admin.partner_id.id + }] + email_1 = 'test1@example.com' + email_2 = 'test2@example.com' + email_3 = self.partner_1.email + self._create_template('mail.test.simple', { + 'attachment_ids': [(0, 0, _attachments[0]), (0, 0, _attachments[1])], + 'partner_to': '%s,%s' % (self.partner_2.id, self.user_admin.partner_id.id), + 'email_to': '%s, %s' % (email_1, email_2), + 'email_cc': '%s' % email_3, + }) + # admin should receive emails self.user_admin.write({'notification_type': 'email'}) + # Force the attachments of the template to be in the natural order. + self.email_template.invalidate_cache(['attachment_ids'], ids=self.email_template.ids) - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_composer_comment(self): - composer = self.env['mail.compose.message'].with_context({ - 'default_composition_mode': 'comment', - 'default_model': self.test_record._name, - 'default_res_id': self.test_record.id, - }).with_user(self.user_employee).create({ - 'body': 'Test Body
', - 'partner_ids': [(4, self.partner_1.id), (4, self.partner_2.id)] - }) - composer.send_mail() + test_record.with_user(self.user_employee).message_post_with_template(self.email_template.id, composition_mode='comment') - message = self.test_record.message_ids[0] - self.assertEqual(message.body, 'Test Body
') - self.assertEqual(message.author_id, self.user_employee.partner_id) - self.assertEqual(message.subject, 'Re: %s' % self.test_record.name) - self.assertEqual(message.subtype_id, self.env.ref('mail.mt_comment')) - self.assertEqual(message.partner_ids, self.partner_1 | self.partner_2) - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_composer_comment_parent(self): - parent = self.test_record.message_post(body='Test') - - self.env['mail.compose.message'].with_context({ - 'default_composition_mode': 'comment', - 'default_parent_id': parent.id - }).with_user(self.user_employee).create({ - 'body': 'Mega
', - }).send_mail() - - message = self.test_record.message_ids[0] - self.assertEqual(message.body, 'Mega
') - self.assertEqual(message.parent_id, parent) - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_composer_mass_mail(self): - test_record_2 = self.env['mail.test.simple'].with_context(BaseFunctionalTest._test_context).create({'name': 'Test2'}) - - composer = self.env['mail.compose.message'].with_context({ - 'default_composition_mode': 'mass_mail', - 'default_model': self.test_record._name, - 'default_res_id': False, - 'active_ids': [self.test_record.id, test_record_2.id] - }).with_user(self.user_employee).create({ - 'subject': 'Testing ${object.name}', - 'body': '${object.name}
', - 'partner_ids': [(4, self.partner_1.id), (4, self.partner_2.id)] - }) - composer.with_context({ - 'default_res_id': -1, - 'active_ids': [self.test_record.id, test_record_2.id] - }).send_mail() - - # check mail_mail - mails = self.env['mail.mail'].search([('subject', 'ilike', 'Testing')]) - for mail in mails: - self.assertEqual(mail.recipient_ids, self.partner_1 | self.partner_2, - 'compose wizard: mail_mail mass mailing: mail.mail in mass mail incorrect recipients') - - # check message on test_record - message1 = self.test_record.message_ids[0] - self.assertEqual(message1.subject, 'Testing %s' % self.test_record.name) - self.assertEqual(message1.body, '%s
' % self.test_record.name) - - # check message on test_record_2 - message1 = test_record_2.message_ids[0] - self.assertEqual(message1.subject, 'Testing %s' % test_record_2.name) - self.assertEqual(message1.body, '%s
' % test_record_2.name) - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_composer_mass_mail_active_domain(self): - test_record_2 = self.env['mail.test.simple'].with_context(BaseFunctionalTest._test_context).create({'name': 'Test2'}) - - self.env['mail.compose.message'].with_context({ - 'default_composition_mode': 'mass_mail', - 'default_model': self.test_record._name, - 'default_use_active_domain': True, - 'active_ids': [self.test_record.id], - 'active_domain': [('name', 'in', ['%s' % self.test_record.name, '%s' % test_record_2.name])], - }).with_user(self.user_employee).create({ - 'subject': 'From Composer Test', - 'body': '${object.name}', - }).send_mail() - - self.assertEqual(self.test_record.message_ids[0].subject, 'From Composer Test') - self.assertEqual(test_record_2.message_ids[0].subject, 'From Composer Test') - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_message_compose_mass_mail_no_active_domain(self): - test_record_2 = self.env['mail.test.simple'].with_context(BaseFunctionalTest._test_context).create({'name': 'Test2'}) - - self.env['mail.compose.message'].with_context({ - 'default_composition_mode': 'mass_mail', - 'default_model': self.test_record._name, - 'default_use_active_domain': False, - 'active_ids': [self.test_record.id], - 'active_domain': [('name', 'in', ['%s' % self.test_record.name, '%s' % test_record_2.name])], - }).with_user(self.user_employee).create({ - 'subject': 'From Composer Test', - 'body': '${object.name}', - }).send_mail() - - self.assertEqual(self.test_record.message_ids[0].subject, 'From Composer Test') - self.assertFalse(test_record_2.message_ids.ids) - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_message_compose_portal_ok(self): - portal_user = mail_new_test_user(self.env, login='chell', groups='base.group_portal', name='Chell Gladys') - - with patch.object(MailTestSimple, 'check_access_rights', return_value=True): - ComposerPortal = self.env['mail.compose.message'].with_user(portal_user) - - ComposerPortal.with_context({ - 'default_composition_mode': 'comment', - 'default_model': self.test_record._name, - 'default_res_id': self.test_record.id, - }).create({ - 'subject': 'Subject', - 'body': 'Body text
', - 'partner_ids': []}).send_mail() - - self.assertEqual(self.test_record.message_ids[0].body, 'Body text
') - self.assertEqual(self.test_record.message_ids[0].author_id, portal_user.partner_id) - - ComposerPortal.with_context({ - 'default_composition_mode': 'comment', - 'default_parent_id': self.test_record.message_ids.ids[0], - }).create({ - 'subject': 'Subject', - 'body': 'Body text 2
'}).send_mail() - - self.assertEqual(self.test_record.message_ids[0].body, 'Body text 2
') - self.assertEqual(self.test_record.message_ids[0].author_id, portal_user.partner_id) + new_partners = self.env['res.partner'].search([('email', 'in', [email_1, email_2])]) + self.assertEmails( + self.user_employee.partner_id, + [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], + subject='About %s' % test_record.name, + body_content=test_record.name, + attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) diff --git a/addons/test_mail/tests/test_message_track.py b/addons/test_mail/tests/test_message_track.py index 49d5df613ab..2771e7b8d45 100644 --- a/addons/test_mail/tests/test_message_track.py +++ b/addons/test_mail/tests/test_message_track.py @@ -1,32 +1,17 @@ # -*- coding: utf-8 -*- from email.utils import formataddr +from unittest.mock import patch from odoo.addons.test_mail.tests import common class TestTracking(common.BaseFunctionalTest, common.MockEmails): - def assertTracking(self, message, data): - tracking_values = message.sudo().tracking_value_ids - for field_name, value_type, old_value, new_value in data: - tracking = tracking_values.filtered(lambda track: track.field == field_name) - self.assertEqual(len(tracking), 1) - if value_type in ('char', 'integer'): - self.assertEqual(tracking.old_value_char, old_value) - self.assertEqual(tracking.new_value_char, new_value) - elif value_type in ('many2one'): - self.assertEqual(tracking.old_value_integer, old_value and old_value.id or False) - self.assertEqual(tracking.new_value_integer, new_value and new_value.id or False) - self.assertEqual(tracking.old_value_char, old_value and old_value.display_name or '') - self.assertEqual(tracking.new_value_char, new_value and new_value.display_name or '') - else: - self.assertEqual(1, 0) - def setUp(self): super(TestTracking, self).setUp() - record = self.env['mail.test.full'].with_user(self.user_employee).with_context(common.BaseFunctionalTest._test_context).create({ + record = self.env['mail.test.full'].with_user(self.user_employee).with_context(self._test_context).create({ 'name': 'Test', }) self.record = record.with_context(mail_notrack=False) @@ -120,7 +105,7 @@ class TestTracking(common.BaseFunctionalTest, common.MockEmails): def test_message_track_template_at_create(self): """ Create a record with tracking template on create, template should be sent.""" - Model = self.env['mail.test.full'].with_user(self.user_employee).with_context(common.BaseFunctionalTest._test_context) + Model = self.env['mail.test.full'].with_user(self.user_employee).with_context(self._test_context) Model = Model.with_context(mail_notrack=False) record = Model.create({ 'name': 'Test', @@ -185,3 +170,37 @@ class TestTracking(common.BaseFunctionalTest, common.MockEmails): ('name', '=', 'email_from')]) ir_model_field.with_context(_force_unlink=True).unlink() self.assertEqual(len(record_sudo.message_ids.tracking_value_ids), 0) + + def test_create_partner_from_tracking_multicompany(self): + company1 = self.env['res.company'].create({'name': 'company1'}) + self.env.user.write({'company_ids': [(4, company1.id, False)]}) + self.assertNotEqual(self.env.company, company1) + + email_new_partner = "diamonds@rust.com" + Partner = self.env['res.partner'] + self.assertFalse(Partner.search([('email', '=', email_new_partner)])) + + template = self.env['mail.template'].create({ + 'model_id': self.env['ir.model']._get('mail.test.track').id, + 'name': 'AutoTemplate', + 'subject': 'autoresponse', + 'email_from': self.env.user.email_formatted, + 'email_to': "${object.email_from}", + 'body_html': "