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):