From 46241ce8a92390a797f6b90d6fbd79014439eec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 8 May 2019 14:19:51 +0000 Subject: [PATCH 1/5] [REF] test_mail: lessen data created by default PURPOSE In order to rewrite some tests, remove low-level tests and add coverage first step is to reorganize a bit test_mail content. Several tests cases are spread among several files and finding back some feature coverage tests is not easy. SPECIFICATIONS Quickly clean common class and lessen data creation by default. Offer some tool methods, notably to create portal users used in some tests but not all, or to create mail templates. LINKS Task 1958697 --- addons/test_mail/tests/__init__.py | 13 +- addons/test_mail/tests/common.py | 51 ++++++- addons/test_mail/tests/test_discuss.py | 39 +++--- addons/test_mail/tests/test_invite.py | 9 +- addons/test_mail/tests/test_ir_actions.py | 15 +-- addons/test_mail/tests/test_mail_activity.py | 29 ++-- addons/test_mail/tests/test_mail_channel.py | 8 +- addons/test_mail/tests/test_mail_followers.py | 26 ++-- addons/test_mail/tests/test_mail_mail.py | 83 +++++++++--- addons/test_mail/tests/test_mail_message.py | 127 +++++++++++------- addons/test_mail/tests/test_mail_race.py | 73 ---------- addons/test_mail/tests/test_mail_resend.py | 6 +- addons/test_mail/tests/test_mail_template.py | 70 +++++----- .../test_mail/tests/test_message_compose.py | 38 +++--- addons/test_mail/tests/test_message_track.py | 20 +-- addons/test_mail/tests/test_odoobot.py | 15 ++- 16 files changed, 326 insertions(+), 296 deletions(-) delete mode 100644 addons/test_mail/tests/test_mail_race.py diff --git a/addons/test_mail/tests/__init__.py b/addons/test_mail/tests/__init__.py index 00691b6ffca..7b164b81f7b 100644 --- a/addons/test_mail/tests/__init__.py +++ b/addons/test_mail/tests/__init__.py @@ -1,10 +1,12 @@ # -*- 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 @@ -12,11 +14,8 @@ from . import test_mail_gateway from . import test_mail_template from . import test_message_compose 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_multi_company +from . import test_odoobot from . import test_performance from . import test_res_users -from . import test_odoobot -from . import test_multi_company +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..94528692973 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( @@ -73,16 +80,17 @@ class TestChatterTweaks(BaseFunctionalTest, TestRecipients): "Creation message without tracking values should have been posted") -class TestNotifications(BaseFunctionalTest, MockEmails): +class TestNotifications(BaseFunctionalTest, TestRecipients, MockEmails): - def setUp(self): - self.partner_1 = self.env['res.partner'].with_context(BaseFunctionalTest._test_context).create({ - 'name': 'Valid Lelitre', - 'email': 'valid.lelitre@agrolait.com'}) + @classmethod + def setUpClass(cls): + super(TestNotifications, 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'}) - (self.user_employee | self.user_admin).write({'notification_type': 'inbox'}) - super(TestNotifications, self).setUp() + (cls.user_employee | cls.user_admin).write({'notification_type': 'inbox'}) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_needaction(self): with self.assertNotifications(partner_employee=(1, 'inbox', 'unread'), partner_admin=(0, '', '')): self.test_record.message_post( @@ -95,6 +103,11 @@ class TestNotifications(BaseFunctionalTest, MockEmails): 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_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 @@ -116,16 +129,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) diff --git a/addons/test_mail/tests/test_invite.py b/addons/test_mail/tests/test_invite.py index 87a802820b8..841a980a517 100644 --- a/addons/test_mail/tests/test_invite.py +++ b/addons/test_mail/tests/test_invite.py @@ -9,21 +9,22 @@ class TestInvite(common.BaseFunctionalTest, common.MockEmails): @mute_logger('odoo.addons.mail.models.mail_mail') def test_invite_email(self): - test_partner = self.env['res.partner'].with_context(common.BaseFunctionalTest._test_context).create({ + test_record = self.env['mail.test.simple'].with_context(self._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) + test_partner = self.env['res.partner'].with_context(self._test_context).create({ 'name': 'Valid Lelitre', 'email': 'valid.lelitre@agrolait.com'}) mail_invite = self.env['mail.wizard.invite'].with_context({ 'default_res_model': 'mail.test.simple', - 'default_res_id': self.test_record.id + 'default_res_id': test_record.id }).with_user(self.user_employee).create({ 'partner_ids': [(4, test_partner.id), (4, self.user_admin.partner_id.id)], 'send_mail': True}) mail_invite.add_followers() # check added followers and that emails were sent - self.assertEqual(self.test_record.message_partner_ids, + self.assertEqual(test_record.message_partner_ids, test_partner | self.user_admin.partner_id) - self.assertEqual(self.test_record.message_follower_ids.mapped('channel_id'), + self.assertEqual(test_record.message_follower_ids.mapped('channel_id'), self.env['mail.channel']) self.assertEqual(len(self._mails), 2) diff --git a/addons/test_mail/tests/test_ir_actions.py b/addons/test_mail/tests/test_ir_actions.py index 36ff2a5094e..9a20ee94db3 100644 --- a/addons/test_mail/tests/test_ir_actions.py +++ b/addons/test_mail/tests/test_ir_actions.py @@ -2,27 +2,20 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.addons.base.tests.test_ir_actions import TestServerActionsBase +from odoo.addons.test_mail.tests.common import BaseFunctionalTest -class TestServerActionsEmail(TestServerActionsBase): +class TestServerActionsEmail(BaseFunctionalTest, TestServerActionsBase): def test_action_email(self): - email_template = self.env['mail.template'].create({ - 'name': 'TestTemplate', - 'email_from': 'myself@example.com', - 'email_to': 'brigitte@example.com', - 'partner_to': '%s' % self.test_partner.id, - 'model_id': self.res_partner_model.id, - 'subject': 'About ${object.name}', - 'body_html': '

Dear ${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_channel.py b/addons/test_mail/tests/test_mail_channel.py index f91084e50ba..6f01e5af660 100644 --- a/addons/test_mail/tests/test_mail_channel.py +++ b/addons/test_mail/tests/test_mail_channel.py @@ -13,7 +13,7 @@ class TestChannelAccessRights(common.BaseFunctionalTest, common.MockEmails): @classmethod def setUpClass(cls): super(TestChannelAccessRights, cls).setUpClass() - Channel = cls.env['mail.channel'].with_context(common.BaseFunctionalTest._test_context) + Channel = cls.env['mail.channel'].with_context(cls._test_context) 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') @@ -113,13 +113,13 @@ class TestChannelFeatures(common.BaseFunctionalTest, common.MockEmails): @classmethod def setUpClass(cls): super(TestChannelFeatures, cls).setUpClass() - cls.test_channel = cls.env['mail.channel'].with_context(common.BaseFunctionalTest._test_context).create({ + cls.test_channel = cls.env['mail.channel'].with_context(cls._test_context).create({ 'name': 'Test', 'description': 'Description', 'alias_name': 'test', 'public': 'public', }) - cls.test_partner = cls.env['res.partner'].with_context(common.BaseFunctionalTest._test_context).create({ + cls.test_partner = cls.env['res.partner'].with_context(cls._test_context).create({ 'name': 'Test Partner', 'email': 'test@example.com', }) @@ -202,7 +202,7 @@ class TestChannelFeatures(common.BaseFunctionalTest, common.MockEmails): @mute_logger('odoo.addons.mail.models.mail_mail') def test_channel_out_of_office(self): self.user_employee.out_of_office_message = 'Out' - test_chat = self.env['mail.channel'].with_context(common.BaseFunctionalTest._test_context).create({ + test_chat = self.env['mail.channel'].with_context(self._test_context).create({ 'channel_partner_ids': [(4, self.user_employee.partner_id.id), (4, self.user_admin.partner_id.id)], 'public': 'private', 'channel_type': 'chat', diff --git a/addons/test_mail/tests/test_mail_followers.py b/addons/test_mail/tests/test_mail_followers.py index 10c89ce0869..0d582c19bad 100644 --- a/addons/test_mail/tests/test_mail_followers.py +++ b/addons/test_mail/tests/test_mail_followers.py @@ -4,7 +4,6 @@ from psycopg2 import IntegrityError from odoo.addons.test_mail.tests import common -from odoo.addons.test_mail.tests.common import mail_new_test_user from odoo.tools.misc import mute_logger @@ -13,6 +12,10 @@ class BaseFollowersTest(common.BaseFunctionalTest): @classmethod def setUpClass(cls): super(BaseFollowersTest, cls).setUpClass() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) + cls._create_portal_user() + cls._create_channel_listener() + Subtype = cls.env['mail.message.subtype'] cls.mt_mg_def = Subtype.create({'name': 'mt_mg_def', 'default': True, 'res_model': 'mail.test.simple'}) cls.mt_cl_def = Subtype.create({'name': 'mt_cl_def', 'default': True, 'res_model': 'mail.test'}) @@ -54,15 +57,13 @@ class BaseFollowersTest(common.BaseFunctionalTest): self.assertEqual(follower.subtype_ids, self.default_group_subtypes) def test_followers_subtypes_default_internal(self): - user_portal = mail_new_test_user(self.env, login='chell', groups='base.group_portal', name='Chell Gladys') - test_record = self.test_record.with_user(self.user_employee) - test_record.message_subscribe(partner_ids=[user_portal.partner_id.id]) - self.assertEqual(test_record.message_partner_ids, user_portal.partner_id) + test_record.message_subscribe(partner_ids=[self.partner_portal.id]) + self.assertEqual(test_record.message_partner_ids, self.partner_portal) follower = self.env['mail.followers'].search([ ('res_model', '=', 'mail.test.simple'), ('res_id', '=', test_record.id), - ('partner_id', '=', user_portal.partner_id.id)]) + ('partner_id', '=', self.partner_portal.id)]) self.assertEqual(follower.subtype_ids, self.default_group_subtypes_portal) def test_followers_subtypes_specified(self): @@ -120,8 +121,7 @@ class AdvancedFollowersTest(common.BaseFunctionalTest): @classmethod def setUpClass(cls): super(AdvancedFollowersTest, cls).setUpClass() - - cls.user_portal = mail_new_test_user(cls.env, login='chell', groups='base.group_portal', name='Chell Gladys') + cls._create_portal_user() cls.test_track = cls.env['mail.test.track'].with_user(cls.user_employee).create({ 'name': 'Test', @@ -183,12 +183,12 @@ class AdvancedFollowersTest(common.BaseFunctionalTest): * subscribing to a sub-record as creator applies default subtype values * portal user should not have access to internal subtypes """ - umbrella = self.env['mail.test'].with_context(common.BaseFunctionalTest._test_context).create({ + umbrella = self.env['mail.test'].with_context(self._test_context).create({ 'name': 'Project-Like', }) - umbrella.message_subscribe(partner_ids=[self.user_portal.partner_id.id]) - self.assertEqual(umbrella.message_partner_ids, self.user_portal.partner_id) + umbrella.message_subscribe(partner_ids=[self.partner_portal.id]) + self.assertEqual(umbrella.message_partner_ids, self.partner_portal) sub1 = self.env['mail.test.track'].with_user(self.user_employee).create({ 'name': 'Task-Like Test', @@ -198,9 +198,9 @@ class AdvancedFollowersTest(common.BaseFunctionalTest): all_defaults = self.env['mail.message.subtype'].search([('default', '=', True), '|', ('res_model', '=', 'mail.test.track'), ('res_model', '=', False)]) external_defaults = all_defaults.filtered(lambda subtype: not subtype.internal) - self.assertEqual(sub1.message_partner_ids, self.user_portal.partner_id | self.user_employee.partner_id) + self.assertEqual(sub1.message_partner_ids, self.partner_portal | self.user_employee.partner_id) self.assertEqual( - sub1.message_follower_ids.filtered(lambda fol: fol.partner_id == self.user_portal.partner_id).subtype_ids, + sub1.message_follower_ids.filtered(lambda fol: fol.partner_id == self.partner_portal).subtype_ids, external_defaults | self.sub_umb1) self.assertEqual( sub1.message_follower_ids.filtered(lambda fol: fol.partner_id == self.user_employee.partner_id).subtype_ids, diff --git a/addons/test_mail/tests/test_mail_mail.py b/addons/test_mail/tests/test_mail_mail.py index aebb4734fc3..912ed491aa9 100644 --- a/addons/test_mail/tests/test_mail_mail.py +++ b/addons/test_mail/tests/test_mail_mail.py @@ -2,27 +2,16 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. import itertools +import psycopg2 +from odoo import api +from odoo.addons.base.models.ir_mail_server import MailDeliveryException from odoo.addons.test_mail.tests import common as mail_common from odoo.tests import common from odoo.tools import mute_logger -from odoo.addons.base.models.ir_mail_server import MailDeliveryException -class TestMail(common.SavepointCase, mail_common.MockEmails): - - @classmethod - def setUpClass(cls): - super(TestMail, cls).setUpClass() - - cls.user_employee = cls.env['res.users'].with_context(mail_common.BaseFunctionalTest._test_context).create({ - 'name': 'Ernest Employee', - 'login': 'ernest', - 'email': 'e.e@example.com', - 'signature': '--\nErnest', - 'notification_type': 'email', - 'groups_id': [(6, 0, [cls.env.ref('base.group_user').id])] - }) +class TestMail(mail_common.BaseFunctionalTest, mail_common.MockEmails): @mute_logger('odoo.addons.mail.models.mail_mail') def test_mail_message_notify_from_mail_mail(self): @@ -49,3 +38,67 @@ class TestMail(common.SavepointCase, mail_common.MockEmails): }) self.assertRaises(MailDeliveryException, lambda: mail.send(raise_exception=True)) + + +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_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_mail_resend.py b/addons/test_mail/tests/test_mail_resend.py index cec04958a9a..557eebd4ca7 100644 --- a/addons/test_mail/tests/test_mail_resend.py +++ b/addons/test_mail/tests/test_mail_resend.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_mail_template.py b/addons/test_mail/tests/test_mail_template.py index df3f47b4d95..e128639f60f 100644 --- a/addons/test_mail/tests/test_mail_template.py +++ b/addons/test_mail/tests/test_mail_template.py @@ -12,43 +12,41 @@ from odoo.tools import mute_logger, DEFAULT_SERVER_DATETIME_FORMAT 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) + 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): @@ -68,8 +66,8 @@ class TestMailTemplate(BaseFunctionalTest, MockEmails, TestRecipients): 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, + 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): @@ -118,13 +116,13 @@ class TestMailTemplate(BaseFunctionalTest, MockEmails, TestRecipients): 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, + 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')]) @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'}) + 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', @@ -148,26 +146,26 @@ class TestMailTemplate(BaseFunctionalTest, MockEmails, TestRecipients): 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, + 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=test_record_2.name, - body_content=test_record_2.email_from, + 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, 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) + 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({ @@ -186,7 +184,7 @@ class TestMailTemplate(BaseFunctionalTest, MockEmails, TestRecipients): 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) diff --git a/addons/test_mail/tests/test_message_compose.py b/addons/test_mail/tests/test_message_compose.py index adf1dd80ae6..d57d356262e 100644 --- a/addons/test_mail/tests/test_message_compose.py +++ b/addons/test_mail/tests/test_message_compose.py @@ -16,17 +16,19 @@ from odoo.tools import mute_logger class TestMessagePost(BaseFunctionalTest, MockEmails, TestRecipients): - def setUp(self): - super(TestMessagePost, self).setUp() + @classmethod + def setUpClass(cls): + super(TestMessagePost, cls).setUpClass() + 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_notifications(self): @@ -223,17 +225,19 @@ class TestMessagePost(BaseFunctionalTest, MockEmails, TestRecipients): class TestComposer(BaseFunctionalTest, MockEmails, TestRecipients): - def setUp(self): - super(TestComposer, self).setUp() + @classmethod + def setUpClass(cls): + super(TestComposer, cls).setUpClass() + 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_composer_comment(self): @@ -271,7 +275,7 @@ class TestComposer(BaseFunctionalTest, MockEmails, TestRecipients): @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'}) + 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', @@ -306,7 +310,7 @@ class TestComposer(BaseFunctionalTest, MockEmails, TestRecipients): @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'}) + 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', @@ -324,7 +328,7 @@ class TestComposer(BaseFunctionalTest, MockEmails, TestRecipients): @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'}) + 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', diff --git a/addons/test_mail/tests/test_message_track.py b/addons/test_mail/tests/test_message_track.py index 49d5df613ab..ff1c02f8d5a 100644 --- a/addons/test_mail/tests/test_message_track.py +++ b/addons/test_mail/tests/test_message_track.py @@ -7,26 +7,10 @@ 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 +104,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', diff --git a/addons/test_mail/tests/test_odoobot.py b/addons/test_mail/tests/test_odoobot.py index a494a84bf53..c8d00b31223 100644 --- a/addons/test_mail/tests/test_odoobot.py +++ b/addons/test_mail/tests/test_odoobot.py @@ -11,18 +11,21 @@ from odoo.tests import tagged @tagged("odoobot") class TestOdoobot(BaseFunctionalTest, MockEmails, TestRecipients): - def setUp(self): - super(TestOdoobot, self).setUp() - self.odoobot = self.env.ref("base.partner_root") - self.message_post_default_kwargs = { + @classmethod + def setUpClass(cls): + super(TestOdoobot, cls).setUpClass() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) + + cls.odoobot = cls.env.ref("base.partner_root") + cls.message_post_default_kwargs = { 'body': '', 'attachment_ids': [], 'message_type': 'comment', 'partner_ids': [], 'subtype': 'mail.mt_comment' } - self.odoobot_ping_body = '@OdooBot' % (self.odoobot.id, self.odoobot.id) - self.test_record_employe = self.test_record.with_user(self.user_employee) + cls.odoobot_ping_body = '@OdooBot' % (cls.odoobot.id, cls.odoobot.id) + cls.test_record_employe = cls.test_record.with_user(cls.user_employee) @mute_logger('odoo.addons.mail.models.mail_mail') def test_fetch_listener(self): From 803d87c46df983de98b8d1094714a80a36a0e3ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 6 Sep 2019 09:57:50 +0000 Subject: [PATCH 2/5] [MOV] test_mail: rename some test files PURPOSE In order to rewrite some tests, remove low-level tests and add coverage first step is to reorganize a bit test_mail content. Several tests cases are spread among several files and finding back some feature coverage tests is not easy. SPECIFICATIONS * put channel moderation tests in test_mail_channel; * rename resend to message management; * rename multi company test to redirect tests: LINKS Task 1958697 --- addons/test_mail/tests/__init__.py | 5 ++- addons/test_mail/tests/test_mail_channel.py | 21 ++++++++++++ ...multi_company.py => test_mail_redirect.py} | 0 ...l_resend.py => test_message_management.py} | 0 addons/test_mail/tests/test_res_users.py | 34 ------------------- 5 files changed, 23 insertions(+), 37 deletions(-) rename addons/test_mail/tests/{test_multi_company.py => test_mail_redirect.py} (100%) rename addons/test_mail/tests/{test_mail_resend.py => test_message_management.py} (100%) delete mode 100644 addons/test_mail/tests/test_res_users.py diff --git a/addons/test_mail/tests/__init__.py b/addons/test_mail/tests/__init__.py index 7b164b81f7b..bcd4d38ad86 100644 --- a/addons/test_mail/tests/__init__.py +++ b/addons/test_mail/tests/__init__.py @@ -7,15 +7,14 @@ from . import test_mail_activity from . import test_mail_followers from . import test_mail_message from . import test_mail_mail -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_management from . import test_message_track -from . import test_multi_company from . import test_odoobot from . import test_performance -from . import test_res_users from . import test_update_notification diff --git a/addons/test_mail/tests/test_mail_channel.py b/addons/test_mail/tests/test_mail_channel.py index 6f01e5af660..f1b482028c9 100644 --- a/addons/test_mail/tests/test_mail_channel.py +++ b/addons/test_mail/tests/test_mail_channel.py @@ -311,3 +311,24 @@ class TestChannelModeration(common.Moderation): self.assertEqual(accepted_messages, msg_moderator | msg_email2 | msg_notif) self.assertFalse(msg_admin.channel_ids) self.assertEqual(msg_email2.channel_ids, self.channel_1) + + def test_user_is_moderator(self): + self.assertTrue(self.user_employee.is_moderator) + self.assertFalse(self.user_admin.is_moderator) + self.assertTrue(self.user_employee_2.is_moderator) + + def test_user_moderation_counter(self): + self._create_new_message(self.channel_1.id, status='pending_moderation', author=self.partner_admin) + self._create_new_message(self.channel_1.id, status='accepted', author=self.partner_admin) + self._create_new_message(self.channel_1.id, status='accepted', author=self.partner_employee) + self._create_new_message(self.channel_1.id, status='pending_moderation', author=self.partner_employee) + self._create_new_message(self.channel_1.id, status='accepted', author=self.partner_employee_2) + + self.assertEqual(self.user_employee.moderation_counter, 2) + self.assertEqual(self.user_employee_2.moderation_counter, 0) + self.assertEqual(self.user_admin.moderation_counter, 0) + + self.channel_1.write({'channel_partner_ids': [(4, self.partner_employee_2.id)], 'moderator_ids': [(4, self.user_employee_2.id)]}) + self.assertEqual(self.user_employee.moderation_counter, 2) + self.assertEqual(self.user_employee_2.moderation_counter, 0) + self.assertEqual(self.user_admin.moderation_counter, 0) 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_resend.py b/addons/test_mail/tests/test_message_management.py similarity index 100% rename from addons/test_mail/tests/test_mail_resend.py rename to addons/test_mail/tests/test_message_management.py diff --git a/addons/test_mail/tests/test_res_users.py b/addons/test_mail/tests/test_res_users.py deleted file mode 100644 index 4ae3ca00265..00000000000 --- a/addons/test_mail/tests/test_res_users.py +++ /dev/null @@ -1,34 +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 - - -@tagged('moderation') -class TestMessageModeration(common.Moderation): - - @classmethod - def setUpClass(cls): - super(TestMessageModeration, cls).setUpClass() - - def test_is_moderator(self): - self.assertTrue(self.user_employee.is_moderator) - self.assertFalse(self.user_admin.is_moderator) - self.assertTrue(self.user_employee_2.is_moderator) - - def test_moderation_counter(self): - self._create_new_message(self.channel_1.id, status='pending_moderation', author=self.partner_admin) - self._create_new_message(self.channel_1.id, status='accepted', author=self.partner_admin) - self._create_new_message(self.channel_1.id, status='accepted', author=self.partner_employee) - self._create_new_message(self.channel_1.id, status='pending_moderation', author=self.partner_employee) - self._create_new_message(self.channel_1.id, status='accepted', author=self.partner_employee_2) - - self.assertEqual(self.user_employee.moderation_counter, 2) - self.assertEqual(self.user_employee_2.moderation_counter, 0) - self.assertEqual(self.user_admin.moderation_counter, 0) - - self.channel_1.write({'channel_partner_ids': [(4, self.partner_employee_2.id)], 'moderator_ids': [(4, self.user_employee_2.id)]}) - self.assertEqual(self.user_employee.moderation_counter, 2) - self.assertEqual(self.user_employee_2.moderation_counter, 0) - self.assertEqual(self.user_admin.moderation_counter, 0) From 8a8da21d2ecc59542be549812b2c6b89bd86f3db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 6 Sep 2019 10:18:27 +0000 Subject: [PATCH 3/5] [MOV] test_mail: split post and composer tests PURPOSE In order to rewrite some tests, remove low-level tests and add coverage first step is to reorganize a bit test_mail content. Several tests cases are spread among several files and finding back some feature coverage tests is not easy. SPECIFICATIONS Reorganize tests, notably * put message_post related test in test_message_post; * have only composer related test in test_message_compose(r); * put alias tests in test_mail_gateway; * move some discuss tests to post tests as they are linked to notification details, not really Discuss features. LINKS Task 1958697 --- addons/test_mail/tests/__init__.py | 3 +- addons/test_mail/tests/test_discuss.py | 66 ++---- addons/test_mail/tests/test_mail_gateway.py | 8 + .../test_mail/tests/test_message_composer.py | 160 ++++++++++++++ ...essage_compose.py => test_message_post.py} | 200 ++++-------------- 5 files changed, 221 insertions(+), 216 deletions(-) create mode 100644 addons/test_mail/tests/test_message_composer.py rename addons/test_mail/tests/{test_message_compose.py => test_message_post.py} (58%) diff --git a/addons/test_mail/tests/__init__.py b/addons/test_mail/tests/__init__.py index bcd4d38ad86..75891bb0e8d 100644 --- a/addons/test_mail/tests/__init__.py +++ b/addons/test_mail/tests/__init__.py @@ -12,8 +12,9 @@ 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_composerr from . import test_message_management +from . import test_message_post from . import test_message_track from . import test_odoobot from . import test_performance diff --git a/addons/test_mail/tests/test_discuss.py b/addons/test_mail/tests/test_discuss.py index 94528692973..d81f989383e 100644 --- a/addons/test_mail/tests/test_discuss.py +++ b/addons/test_mail/tests/test_discuss.py @@ -79,49 +79,24 @@ 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, TestRecipients, MockEmails): + # creating a mail-thread record should not invalidate the whole cache + self.env['res.partner'].create({'name': 'Actual Partner'}) + self.assertTrue(record.name) + + +class TestDiscuss(BaseFunctionalTest, TestRecipients, MockEmails): @classmethod def setUpClass(cls): - super(TestNotifications, cls).setUpClass() - cls._create_portal_user() + 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'}) - (cls.user_employee | cls.user_admin).write({'notification_type': 'inbox'}) - - @mute_logger('odoo.addons.mail.models.mail_mail') - 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]) - - 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_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') - def test_set_message_done_user(self): with self.assertNotifications(partner_employee=(0, '', '')): message = self.test_record.message_post( @@ -145,20 +120,3 @@ class TestNotifications(BaseFunctionalTest, TestRecipients, MockEmails): msg.toggle_message_starred() 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) diff --git a/addons/test_mail/tests/test_mail_gateway.py b/addons/test_mail/tests/test_mail_gateway.py index 6784816dc9f..9848b26f0c7 100644 --- a/addons/test_mail/tests/test_mail_gateway.py +++ b/addons/test_mail/tests/test_mail_gateway.py @@ -69,6 +69,14 @@ class TestEmailParsing(BaseFunctionalTest, MockEmails): self.env['mail.thread'].message_parse(email.message_from_string(pycompat.to_text(test_mail_data.MAIL_XHTML))) +@tagged('mail_gateway') +class TestMailAlias(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') + + @tagged('mail_gateway') class TestMailgateway(BaseFunctionalTest, MockEmails): diff --git a/addons/test_mail/tests/test_message_composer.py b/addons/test_mail/tests/test_message_composer.py new file mode 100644 index 00000000000..658df986d6b --- /dev/null +++ b/addons/test_mail/tests/test_message_composer.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +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.models.test_mail_models import MailTestSimple +from odoo.tools import mute_logger + + +class TestComposer(BaseFunctionalTest, MockEmails, TestRecipients): + + @classmethod + def setUpClass(cls): + super(TestComposer, cls).setUpClass() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) + + # configure mailing + 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 + cls.user_admin.write({'notification_type': 'email'}) + + @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() + + 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) diff --git a/addons/test_mail/tests/test_message_compose.py b/addons/test_mail/tests/test_message_post.py similarity index 58% rename from addons/test_mail/tests/test_message_compose.py rename to addons/test_mail/tests/test_message_post.py index d57d356262e..ed48f16f5cc 100644 --- a/addons/test_mail/tests/test_message_compose.py +++ b/addons/test_mail/tests/test_message_post.py @@ -7,18 +7,18 @@ 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): @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 @@ -27,9 +27,42 @@ class TestMessagePost(BaseFunctionalTest, MockEmails, TestRecipients): 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 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): _body, _body_alt, _subject = '

Test Body

', 'Test Body', 'Test Subject' @@ -155,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') @@ -221,154 +250,3 @@ class TestMessagePost(BaseFunctionalTest, MockEmails, TestRecipients): self.assertEqual(new_notification.notified_partner_ids, self.partner_1 | self.user_employee.partner_id) 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): - - @classmethod - def setUpClass(cls): - super(TestComposer, cls).setUpClass() - cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) - - # configure mailing - 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 - cls.user_admin.write({'notification_type': 'email'}) - - @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() - - 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) From 6ccaae1b2f3fbbbd686de976e10439c45f7804de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 6 Sep 2019 11:42:50 +0000 Subject: [PATCH 4/5] [MOV] test_mail: split cc tests to either discuss or mailgateway tests PURPOSE In order to rewrite some tests, remove low-level tests and add coverage first step is to reorganize a bit test_mail content. Several tests cases are spread among several files and finding back some feature coverage tests is not easy. SPECIFICATIONS Split cc tests to either discuss or mail gateway tests. It allows to remove an unnecessary file. LINKS Task 1958697 --- addons/test_mail/tests/__init__.py | 3 +- addons/test_mail/tests/test_discuss.py | 10 ++++ addons/test_mail/tests/test_mail_cc.py | 63 --------------------- addons/test_mail/tests/test_mail_gateway.py | 49 ++++++++++++++-- 4 files changed, 56 insertions(+), 69 deletions(-) delete mode 100644 addons/test_mail/tests/test_mail_cc.py diff --git a/addons/test_mail/tests/__init__.py b/addons/test_mail/tests/__init__.py index 75891bb0e8d..78d3b1516b6 100644 --- a/addons/test_mail/tests/__init__.py +++ b/addons/test_mail/tests/__init__.py @@ -7,12 +7,11 @@ from . import test_mail_activity from . import test_mail_followers from . import test_mail_message from . import test_mail_mail -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_composerr +from . import test_message_composer from . import test_message_management from . import test_message_post from . import test_message_track diff --git a/addons/test_mail/tests/test_discuss.py b/addons/test_mail/tests/test_discuss.py index d81f989383e..be255274ea3 100644 --- a/addons/test_mail/tests/test_discuss.py +++ b/addons/test_mail/tests/test_discuss.py @@ -120,3 +120,13 @@ class TestDiscuss(BaseFunctionalTest, TestRecipients, MockEmails): msg.toggle_message_starred() self.assertFalse(msg.starred) self.assertTrue(msg_emp.starred) + + @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, cc3 '}) + suggestions = record._message_get_suggested_recipients()[record.id] + self.assertEqual(sorted(suggestions), [ + (False, 'cc1@example.com', 'CC Email'), + (False, 'cc2@example.com', 'CC Email'), + (False, 'cc3 ', 'CC Email') + ], 'cc should be in suggestions') 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 Lelitre ' - cls.alias = cls.env['mail.alias'].create({ - 'alias_name': 'cc_record', - 'alias_user_id': False, - 'alias_model_id': cls.env['ir.model']._get('mail.test.cc').id, - 'alias_contact': 'everyone'}) - - cls.env['ir.config_parameter'].set_param('mail.bounce.alias', 'bounce.test') - cls.env['ir.config_parameter'].set_param('mail.catchall.domain', 'test.com') - cls.env['ir.config_parameter'].set_param('mail.catchall.alias', 'catchall.test') - - @mute_logger('odoo.addons.mail.models.mail_thread') - def test_message_cc_new(self): - record = self.format_and_process(MAIL_TEMPLATE, self.email_from, 'cc_record@test.com', - cc='cc1@example.com, cc2@example.com', target_model='mail.test.cc') - cc = email_split_and_format(record.email_cc) - self.assertEqual(sorted(cc), ['cc1@example.com', 'cc2@example.com']) - - @mute_logger('odoo.addons.mail.models.mail_thread') - def test_message_cc_update_with_old(self): - record = self.env['mail.test.cc'].create({'email_cc': 'cc1 , cc2@example.com'}) - self.alias.write({'alias_force_thread_id': record.id}) - - self.format_and_process(MAIL_TEMPLATE, self.email_from, 'cc_record@test.com', - cc='cc2 , cc3@example.com', target_model='mail.test.cc') - cc = email_split_and_format(record.email_cc) - self.assertEqual(sorted(cc), ['cc1 ', 'cc2@example.com', 'cc3@example.com'], 'new cc should have been added on record (unique)') - - @mute_logger('odoo.addons.mail.models.mail_thread') - def test_message_cc_update_no_old(self): - record = self.env['mail.test.cc'].create({}) - self.alias.write({'alias_force_thread_id': record.id}) - - self.format_and_process(MAIL_TEMPLATE, self.email_from, 'cc_record@test.com', - cc='cc2 , cc3@example.com', target_model='mail.test.cc') - cc = email_split_and_format(record.email_cc) - self.assertEqual(sorted(cc), ['cc2 ', 'cc3@example.com'], 'new cc should have been added on record (unique)') - - @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, cc3 '}) - suggestions = record._message_get_suggested_recipients()[record.id] - self.assertEqual(sorted(suggestions), [ - (False, 'cc1@example.com', 'CC Email'), - (False, 'cc2@example.com', 'CC Email'), - (False, 'cc3 ', 'CC Email') - ], 'cc should be in suggestions') diff --git a/addons/test_mail/tests/test_mail_gateway.py b/addons/test_mail/tests/test_mail_gateway.py index 9848b26f0c7..52ed239bc0e 100644 --- a/addons/test_mail/tests/test_mail_gateway.py +++ b/addons/test_mail/tests/test_mail_gateway.py @@ -15,7 +15,7 @@ from odoo.addons.test_mail.models.test_mail_models import MailTestGateway from odoo.addons.test_mail.tests.common import BaseFunctionalTest, MockEmails from odoo.addons.test_mail.tests.common import mail_new_test_user from odoo.tests import tagged -from odoo.tools import mute_logger, pycompat +from odoo.tools import email_split_and_format, mute_logger, pycompat @tagged('mail_gateway') @@ -113,9 +113,7 @@ class TestMailgateway(BaseFunctionalTest, MockEmails): 'message_id': '<123456-openerp-%s-mail.test.gateway@%s>' % (cls.test_record.id, socket.gethostname()), }) - cls.env['ir.config_parameter'].set_param('mail.bounce.alias', 'bounce.test') - cls.env['ir.config_parameter'].set_param('mail.catchall.domain', 'test.com') - cls.env['ir.config_parameter'].set_param('mail.catchall.alias', 'catchall.test') + cls._init_mail_gateway() # -------------------------------------------------- # Base low-level tests @@ -748,3 +746,46 @@ class TestMailgateway(BaseFunctionalTest, MockEmails): self.assertEqual(len(record), 1) self.assertEqual(record.name, 'Spammy') self.assertEqual(record._name, 'mail.test.gateway') + + +class TestMailThreadCC(BaseFunctionalTest, MockEmails): + + @classmethod + def setUpClass(cls): + super(TestMailThreadCC, cls).setUpClass() + + cls.email_from = 'Sylvie Lelitre ' + cls.alias = cls.env['mail.alias'].create({ + 'alias_name': 'cc_record', + 'alias_user_id': False, + 'alias_model_id': cls.env['ir.model']._get('mail.test.cc').id, + 'alias_contact': 'everyone'}) + + cls._init_mail_gateway() + + @mute_logger('odoo.addons.mail.models.mail_thread') + def test_message_cc_new(self): + record = self.format_and_process(MAIL_TEMPLATE, self.email_from, 'cc_record@test.com', + cc='cc1@example.com, cc2@example.com', target_model='mail.test.cc') + cc = email_split_and_format(record.email_cc) + self.assertEqual(sorted(cc), ['cc1@example.com', 'cc2@example.com']) + + @mute_logger('odoo.addons.mail.models.mail_thread') + def test_message_cc_update_with_old(self): + record = self.env['mail.test.cc'].create({'email_cc': 'cc1 , cc2@example.com'}) + self.alias.write({'alias_force_thread_id': record.id}) + + self.format_and_process(MAIL_TEMPLATE, self.email_from, 'cc_record@test.com', + cc='cc2 , cc3@example.com', target_model='mail.test.cc') + cc = email_split_and_format(record.email_cc) + self.assertEqual(sorted(cc), ['cc1 ', 'cc2@example.com', 'cc3@example.com'], 'new cc should have been added on record (unique)') + + @mute_logger('odoo.addons.mail.models.mail_thread') + def test_message_cc_update_no_old(self): + record = self.env['mail.test.cc'].create({}) + self.alias.write({'alias_force_thread_id': record.id}) + + self.format_and_process(MAIL_TEMPLATE, self.email_from, 'cc_record@test.com', + cc='cc2 , cc3@example.com', target_model='mail.test.cc') + cc = email_split_and_format(record.email_cc) + self.assertEqual(sorted(cc), ['cc2 ', 'cc3@example.com'], 'new cc should have been added on record (unique)') From 62bd4c07f4c0cfdedcaedb08614854d3dc9e6cb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 6 Sep 2019 13:19:15 +0000 Subject: [PATCH 5/5] [MOV] test_mail: move composer and post tests from template tests PURPOSE In order to rewrite some tests, remove low-level tests and add coverage first step is to reorganize a bit test_mail content. Several tests cases are spread among several files and finding back some feature coverage tests is not easy. SPECIFICATIONS Reorganize tests, notably * put composer with template tests in with composer tests; * put post with template tests with post tests; * put tracking multi company test with tracking tests; LINKS Task 1958697 --- addons/test_mail/tests/test_mail_template.py | 171 +----------------- .../test_mail/tests/test_message_composer.py | 161 +++++++++++++++++ addons/test_mail/tests/test_message_post.py | 41 +++++ addons/test_mail/tests/test_message_track.py | 35 ++++ 4 files changed, 238 insertions(+), 170 deletions(-) diff --git a/addons/test_mail/tests/test_mail_template.py b/addons/test_mail/tests/test_mail_template.py index e128639f60f..5ef9d8277a2 100644 --- a/addons/test_mail/tests/test_mail_template.py +++ b/addons/test_mail/tests/test_mail_template.py @@ -2,12 +2,9 @@ # 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): @@ -48,138 +45,6 @@ class TestMailTemplate(BaseFunctionalTest, MockEmails, TestRecipients): # 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_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='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')]) - - @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') - @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) @@ -239,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': "
A nice body
", - }) - - def patched_message_track_post_template(*args, **kwargs): - if args[0]._name == "mail.test.track": - args[0].message_post_with_template(template.id) - return True - - with patch('odoo.addons.mail.models.mail_thread.MailThread._message_track_post_template', patched_message_track_post_template): - self.env['mail.test.track'].create({ - 'email_from': email_new_partner, - 'company_id': company1.id, - 'user_id': self.env.user.id, # trigger track template - }) - - new_partner = Partner.search([('email', '=', email_new_partner)]) - self.assertTrue(new_partner) - self.assertEqual(new_partner.company_id, company1) diff --git a/addons/test_mail/tests/test_message_composer.py b/addons/test_mail/tests/test_message_composer.py index 658df986d6b..ae0ecbcd483 100644 --- a/addons/test_mail/tests/test_message_composer.py +++ b/addons/test_mail/tests/test_message_composer.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +import base64 + from unittest.mock import patch from odoo.addons.test_mail.tests.common import BaseFunctionalTest, MockEmails, TestRecipients @@ -158,3 +160,162 @@ class TestComposer(BaseFunctionalTest, MockEmails, TestRecipients): 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_message_post.py b/addons/test_mail/tests/test_message_post.py index ed48f16f5cc..2eecfb98b9e 100644 --- a/addons/test_mail/tests/test_message_post.py +++ b/addons/test_mail/tests/test_message_post.py @@ -250,3 +250,44 @@ class TestMessagePost(BaseFunctionalTest, TestRecipients, MockEmails): self.assertEqual(new_notification.notified_partner_ids, self.partner_1 | self.user_employee.partner_id) self.assertNotIn(new_notification, self.test_record.message_ids) # todo xdo add test message_notify on thread with followers and stuff + + @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) + + 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', [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 ff1c02f8d5a..2771e7b8d45 100644 --- a/addons/test_mail/tests/test_message_track.py +++ b/addons/test_mail/tests/test_message_track.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from email.utils import formataddr +from unittest.mock import patch from odoo.addons.test_mail.tests import common @@ -169,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': "
A nice body
", + }) + + def patched_message_track_post_template(*args, **kwargs): + if args[0]._name == "mail.test.track": + args[0].message_post_with_template(template.id) + return True + + with patch('odoo.addons.mail.models.mail_thread.MailThread._message_track_post_template', patched_message_track_post_template): + self.env['mail.test.track'].create({ + 'email_from': email_new_partner, + 'company_id': company1.id, + 'user_id': self.env.user.id, # trigger track template + }) + + new_partner = Partner.search([('email', '=', email_new_partner)]) + self.assertTrue(new_partner) + self.assertEqual(new_partner.company_id, company1)