diff options
| author | Christophe Simonis <chs@odoo.com> | 2019-09-13 18:07:59 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2019-09-13 18:07:59 +0200 |
| commit | 6c948c36bbf72dd896e0bff03aa7fbddadcbb0cd (patch) | |
| tree | f8620905c011735d8a3c340c46d1417a54a75972 /addons/test_mail | |
| parent | 48503fcf08eac6fed12e080d4f501f9bbc8d257d (diff) | |
| parent | 197474e5b9ad43ab2d587a98136a1a809ce9a2e7 (diff) | |
[MERGE] forward port branch saas-12.5 up to 197474e5b9a
Diffstat (limited to 'addons/test_mail')
22 files changed, 1001 insertions, 899 deletions
diff --git a/addons/test_mail/tests/__init__.py b/addons/test_mail/tests/__init__.py index 00691b6ffca..78d3b1516b6 100644 --- a/addons/test_mail/tests/__init__.py +++ b/addons/test_mail/tests/__init__.py @@ -1,22 +1,20 @@ # -*- coding: utf-8 -*- +from . import test_invite +from . import test_ir_actions +from . import test_discuss from . import test_mail_activity from . import test_mail_followers from . import test_mail_message from . import test_mail_mail -from . import test_mail_race -from . import test_mail_resend -from . import test_mail_cc from . import test_mail_channel from . import test_mail_gateway +from . import test_mail_redirect from . import test_mail_template -from . import test_message_compose +from . import test_message_composer +from . import test_message_management +from . import test_message_post from . import test_message_track -from . import test_invite -from . import test_ir_actions -from . import test_update_notification -from . import test_discuss -from . import test_performance -from . import test_res_users from . import test_odoobot -from . import test_multi_company +from . import test_performance +from . import test_update_notification diff --git a/addons/test_mail/tests/common.py b/addons/test_mail/tests/common.py index d3c41a16ab1..17d8594a7d9 100644 --- a/addons/test_mail/tests/common.py +++ b/addons/test_mail/tests/common.py @@ -27,15 +27,43 @@ class BaseFunctionalTest(common.SavepointCase): def setUpClass(cls): super(BaseFunctionalTest, cls).setUpClass() - cls.user_employee = mail_new_test_user(cls.env, login='ernest', groups='base.group_user', signature='--\nErnest', name='Ernest Employee') + cls.user_employee = mail_new_test_user(cls.env, login='employee', groups='base.group_user', signature='--\nErnest', name='Ernest Employee') cls.partner_employee = cls.user_employee.partner_id cls.user_admin = cls.env.ref('base.user_admin') cls.partner_admin = cls.env.ref('base.partner_admin') + @classmethod + def _create_channel_listener(cls): cls.channel_listen = cls.env['mail.channel'].with_context(cls._test_context).create({'name': 'Listener'}) - cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) + @classmethod + def _create_portal_user(cls): + cls.user_portal = mail_new_test_user(cls.env, login='chell', groups='base.group_portal', name='Chell Gladys') + cls.partner_portal = cls.user_portal.partner_id + + @classmethod + def _create_template(cls, model, template_values=None): + create_values = { + 'name': 'TestTemplate', + 'subject': 'About ${object.name}', + 'body_html': '<p>Hello ${object.name}</p>', + 'model_id': cls.env['ir.model']._get(model).id, + 'user_signature': False, + } + if template_values: + create_values.update(template_values) + cls.email_template = cls.env['mail.template'].create(create_values) + return cls.email_template + + @classmethod + def _init_mail_gateway(cls): + cls.alias_domain = 'test.com' + cls.alias_catchall = 'catchall.test' + cls.alias_bounce = 'bounce.test' + cls.env['ir.config_parameter'].set_param('mail.bounce.alias', cls.alias_bounce) + cls.env['ir.config_parameter'].set_param('mail.catchall.domain', cls.alias_domain) + cls.env['ir.config_parameter'].set_param('mail.catchall.alias', cls.alias_catchall) @classmethod def _reset_mail_context(cls, record): @@ -62,6 +90,8 @@ class BaseFunctionalTest(common.SavepointCase): init[partner] = { 'na_counter': len([n for n in init_notifs if n.res_partner_id == partner and not n.is_read]), } + if hasattr(self, '_init_mock_build_email'): + self._init_mock_build_email() yield finally: new_notifications = self.env['mail.notification'].sudo().search([ @@ -143,12 +173,27 @@ class BaseFunctionalTest(common.SavepointCase): else: raise AssertionError('Keys %s not found (expected: %s - returned: %s)' % (not_found_keys, repr(expected), repr(notif_messages))) + def assertTracking(self, message, data): + tracking_values = message.sudo().tracking_value_ids + for field_name, value_type, old_value, new_value in data: + tracking = tracking_values.filtered(lambda track: track.field == field_name) + self.assertEqual(len(tracking), 1) + if value_type in ('char', 'integer'): + self.assertEqual(tracking.old_value_char, old_value) + self.assertEqual(tracking.new_value_char, new_value) + elif value_type in ('many2one'): + self.assertEqual(tracking.old_value_integer, old_value and old_value.id or False) + self.assertEqual(tracking.new_value_integer, new_value and new_value.id or False) + self.assertEqual(tracking.old_value_char, old_value and old_value.display_name or '') + self.assertEqual(tracking.new_value_char, new_value and new_value.display_name or '') + else: + self.assertEqual(1, 0) + @contextmanager def sudo(self, login): old_uid = self.uid try: user = self.env['res.users'].sudo().search([('login', '=', login)]) - self.test_record_old = self.test_record # switch user self.uid = user.id self.env = self.env(user=self.uid) diff --git a/addons/test_mail/tests/test_discuss.py b/addons/test_mail/tests/test_discuss.py index 23b707d263f..be255274ea3 100644 --- a/addons/test_mail/tests/test_discuss.py +++ b/addons/test_mail/tests/test_discuss.py @@ -2,11 +2,16 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.addons.test_mail.tests.common import BaseFunctionalTest, TestRecipients, MockEmails -from odoo.addons.test_mail.tests.common import mail_new_test_user +from odoo.tools import mute_logger class TestChatterTweaks(BaseFunctionalTest, TestRecipients): + @classmethod + def setUpClass(cls): + super(TestChatterTweaks, cls).setUpClass() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) + def test_post_no_subscribe_author(self): original = self.test_record.message_follower_ids self.test_record.with_user(self.user_employee).with_context({'mail_create_nosubscribe': True}).message_post( @@ -14,6 +19,7 @@ class TestChatterTweaks(BaseFunctionalTest, TestRecipients): self.assertEqual(self.test_record.message_follower_ids.mapped('partner_id'), original.mapped('partner_id')) self.assertEqual(self.test_record.message_follower_ids.mapped('channel_id'), original.mapped('channel_id')) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_post_no_subscribe_recipients(self): original = self.test_record.message_follower_ids self.test_record.with_user(self.user_employee).with_context({'mail_create_nosubscribe': True}).message_post( @@ -21,6 +27,7 @@ class TestChatterTweaks(BaseFunctionalTest, TestRecipients): self.assertEqual(self.test_record.message_follower_ids.mapped('partner_id'), original.mapped('partner_id')) self.assertEqual(self.test_record.message_follower_ids.mapped('channel_id'), original.mapped('channel_id')) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_post_subscribe_recipients(self): original = self.test_record.message_follower_ids self.test_record.with_user(self.user_employee).with_context({'mail_create_nosubscribe': True, 'mail_post_autofollow': True}).message_post( @@ -72,42 +79,23 @@ class TestChatterTweaks(BaseFunctionalTest, TestRecipients): self.assertEqual(len(rec.sudo().mapped('message_ids.tracking_value_ids')), 0, "Creation message without tracking values should have been posted") + def test_cache_invalidation(self): + """ Test that creating a mail-thread record does not invalidate the whole cache. """ + # make a new record in cache + record = self.env['res.partner'].new({'name': 'Brave New Partner'}) + self.assertTrue(record.name) -class TestNotifications(BaseFunctionalTest, MockEmails): - - def setUp(self): - self.partner_1 = self.env['res.partner'].with_context(BaseFunctionalTest._test_context).create({ - 'name': 'Valid Lelitre', - 'email': 'valid.lelitre@agrolait.com'}) - - (self.user_employee | self.user_admin).write({'notification_type': 'inbox'}) - super(TestNotifications, self).setUp() + # creating a mail-thread record should not invalidate the whole cache + self.env['res.partner'].create({'name': 'Actual Partner'}) + self.assertTrue(record.name) - 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]) +class TestDiscuss(BaseFunctionalTest, TestRecipients, MockEmails): - def test_inactive_follower(self): - # In some case odoobot is follower of a record. - # Even if it shouldn't be the case, we want to be sure that odoobot is not notified - self.test_record._message_subscribe(self.user_employee.partner_id.ids) - with self.assertNotifications(partner_employee=(1, 'inbox', 'unread')): - self.test_record.message_post( - body='Test', message_type='comment', subtype='mail.mt_comment') - self.user_employee.active = False - # at this point, partner is still active and would receive an email notification - self.user_employee.partner_id._write({'active': False}) - with self.assertNotifications(partner_employee=(0, '', '')): - self.test_record.message_post( - body='Test', message_type='comment', subtype='mail.mt_comment') + @classmethod + def setUpClass(cls): + super(TestDiscuss, cls).setUpClass() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) def test_set_message_done_user(self): with self.assertNotifications(partner_employee=(0, '', '')): @@ -116,16 +104,6 @@ class TestNotifications(BaseFunctionalTest, MockEmails): partner_ids=[self.user_employee.partner_id.id]) message.with_user(self.user_employee).set_message_done() - def test_set_message_done_portal(self): - user_portal = mail_new_test_user(self.env, login='chell', groups='base.group_portal', name='Chell Gladys', notification_type='inbox') - self.partner_portal = user_portal.partner_id - - with self.assertNotifications(partner_employee=(1, 'inbox', 'unread'), partner_portal=(1, 'inbox', 'read')): - message = self.test_record.message_post( - body='Test', message_type='comment', subtype='mail.mt_comment', - partner_ids=[self.user_employee.partner_id.id, user_portal.partner_id.id]) - message.with_user(user_portal).set_message_done() - def test_set_star(self): msg = self.test_record.with_user(self.user_admin).message_post(body='My Body', subject='1') msg_emp = self.env['mail.message'].with_user(self.user_employee).browse(msg.id) @@ -143,19 +121,12 @@ class TestNotifications(BaseFunctionalTest, MockEmails): self.assertFalse(msg.starred) self.assertTrue(msg_emp.starred) - -class TestChatterMisc(BaseFunctionalTest): - - def test_alias_setup(self): - alias = self.env['mail.alias'].with_context(alias_model_name='mail.test').create({'alias_name': 'b4r+_#_R3wl$$'}) - self.assertEqual(alias.alias_name, 'b4r+_-_r3wl-', 'Disallowed chars should be replaced by hyphens') - - def test_cache_invalidation(self): - """ Test that creating a mail-thread record does not invalidate the whole cache. """ - # make a new record in cache - record = self.env['res.partner'].new({'name': 'Brave New Partner'}) - self.assertTrue(record.name) - - # creating a mail-thread record should not invalidate the whole cache - self.env['res.partner'].create({'name': 'Actual Partner'}) - self.assertTrue(record.name) + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mail_cc_recipient_suggestion(self): + record = self.env['mail.test.cc'].create({'email_cc': 'cc1@example.com, cc2@example.com, cc3 <cc3@example.com>'}) + 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 <cc3@example.com>', 'CC Email') + ], 'cc should be in suggestions') 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': '<p>Dear ${object.name}, your parent is ${object.parent_id and object.parent_id.name or "False"}</p>', - }) + 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, '<p>Dear TestingPartner, your parent is False</p>') + self.assertEqual(mail.body, '<p>Hello TestingPartner</p>') def test_action_followers(self): self.test_partner.message_unsubscribe(self.test_partner.message_partner_ids.ids) diff --git a/addons/test_mail/tests/test_mail_activity.py b/addons/test_mail/tests/test_mail_activity.py index cb7d913a7e4..f72940b07a5 100644 --- a/addons/test_mail/tests/test_mail_activity.py +++ b/addons/test_mail/tests/test_mail_activity.py @@ -10,8 +10,8 @@ import pytz from odoo import exceptions, tests from odoo.addons.test_mail.tests.common import BaseFunctionalTest -from odoo.addons.test_mail.tests.common import mail_new_test_user from odoo.addons.test_mail.models.test_mail_models import MailTestActivity +from odoo.tools import mute_logger class TestActivityCommon(BaseFunctionalTest): @@ -19,7 +19,7 @@ class TestActivityCommon(BaseFunctionalTest): @classmethod def setUpClass(cls): super(TestActivityCommon, cls).setUpClass() - cls.test_record = cls.env['mail.test.activity'].with_context(BaseFunctionalTest._test_context).create({'name': 'Test'}) + cls.test_record = cls.env['mail.test.activity'].with_context(cls._test_context).create({'name': 'Test'}) # reset ctx cls.test_record = cls.test_record.with_context( mail_create_nolog=False, @@ -31,6 +31,7 @@ class TestActivityCommon(BaseFunctionalTest): @tests.tagged('mail_activity') class TestActivityRights(TestActivityCommon): + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_security_user_access_other(self): activity = self.test_record.with_user(self.user_employee).activity_schedule( 'test_mail.mail_act_test_todo', @@ -38,12 +39,14 @@ class TestActivityRights(TestActivityCommon): self.assertTrue(activity.can_write) activity.write({'user_id': self.user_employee.id}) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_security_user_access_own(self): activity = self.test_record.with_user(self.user_employee).activity_schedule( 'test_mail.mail_act_test_todo') self.assertTrue(activity.can_write) activity.write({'user_id': self.user_admin.id}) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_security_user_noaccess_automated(self): def _employee_crash(*args, **kwargs): """ If employee is test employee, consider he has no access on document """ @@ -90,7 +93,7 @@ class TestActivityRights(TestActivityCommon): class TestActivityFlow(TestActivityCommon): def test_activity_flow_employee(self): - with self.sudo('ernest'): + with self.sudo('employee'): test_record = self.env['mail.test.activity'].browse(self.test_record.id) self.assertEqual(test_record.activity_ids, self.env['mail.activity']) @@ -118,19 +121,7 @@ class TestActivityFlow(TestActivityCommon): self.assertEqual(test_record.activity_ids, self.env['mail.activity']) self.assertEqual(test_record.message_ids[0].subtype_id, self.env.ref('mail.mt_activities')) - def test_activity_flow_portal(self): - portal_user = mail_new_test_user(self.env, login='chell', groups='base.group_portal', name='Chell Gladys') - - with self.sudo('chell'): - test_record = self.env['mail.test.activity'].browse(self.test_record.id) - with self.assertRaises(exceptions.AccessError): - self.env['mail.activity'].create({ - 'summary': 'Test Activity', - 'activity_type_id': self.env.ref('mail.mail_activity_data_email').id, - 'res_model_id': self.env['ir.model']._get(test_record._name).id, - 'res_id': test_record.id, - }) - + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_notify_other_user(self): self.user_admin.notification_type = 'email' rec = self.test_record.with_user(self.user_employee) @@ -151,6 +142,7 @@ class TestActivityFlow(TestActivityCommon): self.assertEqual(activity.create_uid, self.user_employee) self.assertEqual(activity.user_id, self.user_employee) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_dont_notify_no_user_change(self): self.user_employee.notification_type = 'email' activity = self.test_record.activity_schedule('test_mail.mail_act_test_todo', user_id=self.user_employee.id) @@ -162,9 +154,10 @@ class TestActivityFlow(TestActivityCommon): @tests.tagged('mail_activity') class TestActivityMixin(TestActivityCommon): + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_mixin(self): self.user_employee.tz = self.user_admin.tz - with self.sudo('ernest'): + with self.sudo('employee'): self.test_record = self.env['mail.test.activity'].browse(self.test_record.id) self.assertEqual(self.test_record.env.user, self.user_employee) @@ -242,6 +235,7 @@ class TestActivityMixin(TestActivityCommon): self.assertEqual(self.test_record.activity_ids, self.env['mail.activity']) self.assertEqual(len(self.test_record.message_ids), 2) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_mixin_archive(self): rec = self.test_record.with_user(self.user_employee) new_act = rec.activity_schedule( @@ -255,6 +249,7 @@ class TestActivityMixin(TestActivityCommon): self.assertEqual(rec.active, True) self.assertEqual(rec.activity_ids, self.env['mail.activity']) + @mute_logger('odoo.addons.mail.models.mail_mail') def test_activity_mixin_reschedule_user(self): rec = self.test_record.with_user(self.user_employee) rec.activity_schedule( diff --git a/addons/test_mail/tests/test_mail_cc.py b/addons/test_mail/tests/test_mail_cc.py deleted file mode 100644 index 45503d3b649..00000000000 --- a/addons/test_mail/tests/test_mail_cc.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from odoo.addons.test_mail.tests import common
-from odoo.tests import tagged
-from odoo.tools import mute_logger, email_split_and_format
-from odoo.addons.test_mail.data.test_mail_data import MAIL_TEMPLATE
-
-
-@tagged('mail_thread_cc')
-class TestMailCc(common.BaseFunctionalTest, common.MockEmails):
-
- @classmethod
- def setUpClass(cls):
- super(TestMailCc, cls).setUpClass()
-
- cls.email_from = 'Sylvie Lelitre <test.sylvie.lelitre@agrolait.com>'
- 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 <cc1@example.com>, 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 <cc2@example.com>, cc3@example.com', target_model='mail.test.cc')
- cc = email_split_and_format(record.email_cc)
- self.assertEqual(sorted(cc), ['cc1 <cc1@example.com>', '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 <cc2@example.com>, cc3@example.com', target_model='mail.test.cc')
- cc = email_split_and_format(record.email_cc)
- self.assertEqual(sorted(cc), ['cc2 <cc2@example.com>', '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 <cc3@example.com>'})
- 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 <cc3@example.com>', 'CC Email')
- ], 'cc should be in suggestions')
diff --git a/addons/test_mail/tests/test_mail_channel.py b/addons/test_mail/tests/test_mail_channel.py index f91084e50ba..f1b482028c9 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', @@ -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_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_gateway.py b/addons/test_mail/tests/test_mail_gateway.py index eb0ad472b27..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') @@ -70,6 +70,14 @@ class TestEmailParsing(BaseFunctionalTest, MockEmails): @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): @classmethod @@ -105,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 @@ -388,6 +394,7 @@ class TestMailgateway(BaseFunctionalTest, MockEmails): # name order win self.test_record.message_unsubscribe(follower_user.partner_id.ids) + self.test_record.flush() record = self.format_and_process(MAIL_TEMPLATE, self.user_employee.email_formatted, 'groups@test.com', subject='FirstFoundWinner') self.assertEqual(record.create_uid, self.user_employee) self.assertEqual(record.message_ids[0].subject, 'FirstFoundWinner') @@ -739,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 <test.sylvie.lelitre@agrolait.com>' + 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 <cc1@example.com>, 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 <cc2@example.com>, cc3@example.com', target_model='mail.test.cc') + cc = email_split_and_format(record.email_cc) + self.assertEqual(sorted(cc), ['cc1 <cc1@example.com>', '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 <cc2@example.com>, cc3@example.com', target_model='mail.test.cc') + cc = email_split_and_format(record.email_cc) + self.assertEqual(sorted(cc), ['cc2 <cc2@example.com>', 'cc3@example.com'], 'new cc should have been added on record (unique)') 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': '<p>Test</p>', + '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,70 +34,58 @@ 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() - + @mute_logger('odoo.models.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)) + 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))) - @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() + # 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, '%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))) - 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) + # 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') - reply_to_name = self.env.company.name - reply_to_email = '%s@%s' % (alias_catchall, alias_domain) - self.assertEqual(msg.reply_to, formataddr((reply_to_name, reply_to_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))) - def test_mail_message_values_document_no_alias(self): - self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.domain')]).unlink() - + @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]) - self.assertEqual(msg.reply_to, '%s <%s>' % (self.user_employee.name, self.user_employee.email)) + 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)) - @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) - self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.alias')]).unlink() + # no alias domain -> author + self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.domain')]).unlink() 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.company.name, self.alias_record.name) - reply_to_email = '%s@%s' % (self.alias_record.alias_name, 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.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))) - 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) + # 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({ 'model': 'mail.test', @@ -106,9 +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))) + + @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.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' % (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))) + + @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': '<p>Test</p>', - 'notification': True, - 'state': 'outgoing', - 'recipient_ids': [(4, self.partner.id)] - }) - message = self.env['mail.message'].create({ - 'subject': 'S', - 'body': 'B', - 'subtype_id': self.ref('mail.mt_comment'), - 'notification_ids': [(0, 0, { - 'res_partner_id': self.partner.id, - 'mail_id': mail.id, - 'notification_type': 'email', - 'is_read': True, - 'notification_status': 'ready', - })], - }) - notif = self.env['mail.notification'].search([('res_partner_id', '=', self.partner.id)]) - # we need to commit transaction or cr will keep the lock on notif - self.cr.commit() - - # patch send_email in order to create a concurent update and check the notif is already locked by _send() - this = self # coding in javascript ruinned my life - bounce_deferred = [] - @api.model - def send_email(self, message, *args, **kwargs): - with this.registry.cursor() as cr, mute_logger('odoo.sql_db'): - try: - # try ro aquire lock (no wait) on notification (should fail) - cr.execute("SELECT notification_status FROM mail_message_res_partner_needaction_rel WHERE id = %s FOR UPDATE NOWAIT", [notif.id]) - except psycopg2.OperationalError: - # record already locked by send, all good - bounce_deferred.append(True) - else: - # this should trigger psycopg2.extensions.TransactionRollbackError in send(). - # Only here to simulate the initial use case - # If the record is lock, this line would create a deadlock since we are in the same thread - # In practice, the update will wait the end of the send() transaction and set the notif as bounce, as expeced - cr.execute("UPDATE mail_message_res_partner_needaction_rel SET notification_status='bounce' WHERE id = %s", [notif.id]) - return message['Message-Id'] - self.env['ir.mail_server']._patch_method('send_email', send_email) - - mail.send() - - self.assertTrue(bounce_deferred, "The bounce should have been deferred") - self.assertEqual(notif.notification_status, 'sent') - - # some cleaning since we commited the cr - notif.unlink() - message.unlink() - mail.unlink() - self.partner.unlink() - self.env.cr.commit() diff --git a/addons/test_mail/tests/test_multi_company.py b/addons/test_mail/tests/test_mail_redirect.py index 6149e2f429b..6149e2f429b 100644 --- a/addons/test_mail/tests/test_multi_company.py +++ b/addons/test_mail/tests/test_mail_redirect.py diff --git a/addons/test_mail/tests/test_mail_template.py b/addons/test_mail/tests/test_mail_template.py index df3f47b4d95..5ef9d8277a2 100644 --- a/addons/test_mail/tests/test_mail_template.py +++ b/addons/test_mail/tests/test_mail_template.py @@ -2,191 +2,54 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. import base64 -from datetime import datetime, timedelta -from unittest.mock import patch from odoo.addons.test_mail.tests.common import BaseFunctionalTest, MockEmails, TestRecipients -from odoo.addons.test_mail.tests.common import mail_new_test_user -from odoo.tools import mute_logger, DEFAULT_SERVER_DATETIME_FORMAT +from odoo.tools import mute_logger class TestMailTemplate(BaseFunctionalTest, MockEmails, TestRecipients): - def setUp(self): - super(TestMailTemplate, self).setUp() + @classmethod + def setUpClass(cls): + super(TestMailTemplate, cls).setUpClass() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) - self.user_employee.write({ - 'groups_id': [(4, self.env.ref('base.group_partner_manager').id)], + cls.user_employee.write({ + 'groups_id': [(4, cls.env.ref('base.group_partner_manager').id)], }) - self._attachments = [{ + cls._attachments = [{ 'name': 'first.txt', 'datas': base64.b64encode(b'My first attachment'), 'res_model': 'res.partner', - 'res_id': self.user_admin.partner_id.id + 'res_id': cls.user_admin.partner_id.id }, { 'name': 'second.txt', 'datas': base64.b64encode(b'My second attachment'), 'res_model': 'res.partner', - 'res_id': self.user_admin.partner_id.id + 'res_id': cls.user_admin.partner_id.id }] - self.email_1 = 'test1@example.com' - self.email_2 = 'test2@example.com' - self.email_3 = self.partner_1.email - self.email_template = self.env['mail.template'].create({ - 'model_id': self.env['ir.model']._get('mail.test.simple').id, - 'name': 'Pigs Template', - 'subject': '${object.name}', - 'body_html': '${object.email_from}', - 'user_signature': False, - 'attachment_ids': [(0, 0, self._attachments[0]), (0, 0, self._attachments[1])], - 'partner_to': '%s,%s' % (self.partner_2.id, self.user_admin.partner_id.id), - 'email_to': '%s, %s' % (self.email_1, self.email_2), - 'email_cc': '%s' % self.email_3}) + cls.email_1 = 'test1@example.com' + cls.email_2 = 'test2@example.com' + cls.email_3 = cls.partner_1.email + cls._create_template('mail.test.simple', { + 'attachment_ids': [(0, 0, cls._attachments[0]), (0, 0, cls._attachments[1])], + 'partner_to': '%s,%s' % (cls.partner_2.id, cls.user_admin.partner_id.id), + 'email_to': '%s, %s' % (cls.email_1, cls.email_2), + 'email_cc': '%s' % cls.email_3, + }) # admin should receive emails - self.user_admin.write({'notification_type': 'email'}) + cls.user_admin.write({'notification_type': 'email'}) # Force the attachments of the template to be in the natural order. - self.email_template.invalidate_cache(['attachment_ids'], ids=self.email_template.ids) - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_composer_w_template(self): - composer = self.env['mail.compose.message'].with_user(self.user_employee).with_context({ - 'default_composition_mode': 'comment', - 'default_model': 'mail.test.simple', - 'default_res_id': self.test_record.id, - 'default_template_id': self.email_template.id, - }).create({'subject': 'Forget me subject', 'body': 'Dummy body'}) - - # perform onchange and send emails - values = composer.onchange_template_id(self.email_template.id, 'comment', self.test_record._name, self.test_record.id)['value'] - composer.write(values) - composer.send_mail() - - new_partners = self.env['res.partner'].search([('email', 'in', [self.email_1, self.email_2])]) - self.assertEmails( - self.user_employee.partner_id, - [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], - subject=self.test_record.name, - body_content=self.test_record.email_from, - attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) - - def test_composer_template_onchange_attachments(self): - """Tests that all attachments are added to the composer, - static attachments are not duplicated and while reports are re-generated, - and that intermediary attachments are dropped.""" - - composer = self.env['mail.compose.message'].with_context(default_attachment_ids=[]).create({}) - report_template = self.env.ref('web.action_report_externalpreview') - template_1 = self.email_template.copy({ - 'report_template': report_template.id, - }) - template_2 = self.email_template.copy({ - 'attachment_ids': False, - 'report_template': report_template.id, - }) - - onchange_templates = [template_1, template_2, template_1, False] - attachments_onchange = [composer.attachment_ids] - # template_1 has two static attachments and one dynamically generated report, - # template_2 only has the report, so we should get 3, 1, 3 attachments - attachment_numbers = [0, 3, 1, 3, 0] - - for template in onchange_templates: - onchange = composer.onchange_template_id( - template.id if template else False, 'comment', self.test_record._name, self.test_record.id - ) - composer.update(onchange['value']) - attachments_onchange.append(composer.attachment_ids) - - self.assertEqual( - [len(attachments) for attachments in attachments_onchange], - attachment_numbers, - ) - - self.assertTrue( - len(attachments_onchange[1] & attachments_onchange[3]) == 2, - "The two static attachments on the template should be common to the two onchanges" - ) - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_post_post_w_template(self): - self.test_record.with_user(self.user_employee).message_post_with_template(self.email_template.id, composition_mode='comment') - - new_partners = self.env['res.partner'].search([('email', 'in', [self.email_1, self.email_2])]) - self.assertEmails( - self.user_employee.partner_id, - [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], - subject=self.test_record.name, - body_content=self.test_record.email_from, - attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_composer_w_template_mass_mailing(self): - test_record_2 = self.env['mail.test.simple'].with_context(BaseFunctionalTest._test_context).create({'name': 'Test2', 'email_from': 'laurie.poiret@example.com'}) - - composer = self.env['mail.compose.message'].with_user(self.user_employee).with_context({ - 'default_composition_mode': 'mass_mail', - # 'default_notify': True, - 'default_notify': False, - 'default_model': 'mail.test.simple', - 'default_res_id': self.test_record.id, - 'default_template_id': self.email_template.id, - 'active_ids': [self.test_record.id, test_record_2.id] - }).create({}) - values = composer.onchange_template_id(self.email_template.id, 'mass_mail', 'mail.test.simple', self.test_record.id)['value'] - composer.write(values) - composer.send_mail() - - new_partners = self.env['res.partner'].search([('email', 'in', [self.email_1, self.email_2])]) - # hack to use assertEmails - self._mails_record1 = [dict(mail) for mail in self._mails if '%s-%s' % (self.test_record.id, self.test_record._name) in mail['message_id']] - self._mails_record2 = [dict(mail) for mail in self._mails if '%s-%s' % (test_record_2.id, test_record_2._name) in mail['message_id']] - - self._mails = self._mails_record1 - self.assertEmails( - self.user_employee.partner_id, - [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], - subject=self.test_record.name, - body_content=self.test_record.email_from, - attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) - - self._mails = self._mails_record2 - self.assertEmails( - self.user_employee.partner_id, - [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], - subject=test_record_2.name, - body_content=test_record_2.email_from, - attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) - - message_1 = self.test_record.message_ids[0] - message_2 = test_record_2.message_ids[0] - - # messages effectively posted - self.assertEqual(message_1.subject, self.test_record.name) - self.assertEqual(message_2.subject, test_record_2.name) - self.assertIn(self.test_record.email_from, message_1.body) - self.assertIn(test_record_2.email_from, message_2.body) - - def test_composer_template_save(self): - self.env['mail.compose.message'].with_context({ - 'default_composition_mode': 'comment', - 'default_model': 'mail.test.simple', - 'default_res_id': self.test_record.id, - }).create({ - 'subject': 'Forget me subject', - 'body': '<p>Dummy body</p>' - }).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, '<p>Dummy body</p>', 'email_template incorrect body_html') + cls.email_template.invalidate_cache(['attachment_ids'], ids=cls.email_template.ids) @mute_logger('odoo.addons.mail.models.mail_mail') def test_template_send_email(self): mail_id = self.email_template.send_mail(self.test_record.id) mail = self.env['mail.mail'].browse(mail_id) - self.assertEqual(mail.subject, self.test_record.name) + self.assertEqual(mail.subject, 'About %s' % self.test_record.name) self.assertEqual(mail.email_to, self.email_template.email_to) self.assertEqual(mail.email_cc, self.email_template.email_cc) self.assertEqual(mail.recipient_ids, self.partner_2 | self.user_admin.partner_id) @@ -241,37 +104,3 @@ class TestMailTemplate(BaseFunctionalTest, MockEmails, TestRecipients): # self.env['mail.mail'].process_email_queue(ids=[mail_in_2_days.id]) # self.assertEqual(mail_in_2_days.state, 'outgoing') # self.assertEqual(mail_now.exists() | mail_in_2_days.exists(), mail_in_2_days) - - def test_create_partner_from_tracking_multicompany(self): - company1 = self.env['res.company'].create({'name': 'company1'}) - self.env.user.write({'company_ids': [(4, company1.id, False)]}) - self.assertNotEqual(self.env.company, company1) - - email_new_partner = "diamonds@rust.com" - Partner = self.env['res.partner'] - self.assertFalse(Partner.search([('email', '=', email_new_partner)])) - - template = self.env['mail.template'].create({ - 'model_id': self.env['ir.model']._get('mail.test.track').id, - 'name': 'AutoTemplate', - 'subject': 'autoresponse', - 'email_from': self.env.user.email_formatted, - 'email_to': "${object.email_from}", - 'body_html': "<div>A nice body</div>", - }) - - 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 new file mode 100644 index 00000000000..ae0ecbcd483 --- /dev/null +++ b/addons/test_mail/tests/test_message_composer.py @@ -0,0 +1,321 @@ +# -*- 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 +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': '<p>Test Body</p>', + '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, '<p>Test Body</p>') + 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': '<p>Mega</p>', + }).send_mail() + + message = self.test_record.message_ids[0] + self.assertEqual(message.body, '<p>Mega</p>') + 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': '<p>${object.name}</p>', + '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, '<p>%s</p>' % 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, '<p>%s</p>' % 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': '<p>Body text</p>', + 'partner_ids': []}).send_mail() + + self.assertEqual(self.test_record.message_ids[0].body, '<p>Body text</p>') + 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': '<p>Body text 2</p>'}).send_mail() + + self.assertEqual(self.test_record.message_ids[0].body, '<p>Body text 2</p>') + 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': '<p>Dummy body</p>' + }).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, '<p>Dummy body</p>', 'email_template incorrect body_html') diff --git a/addons/test_mail/tests/test_mail_resend.py b/addons/test_mail/tests/test_message_management.py index a2c94ae65e1..bfdf1ccf5b0 100644 --- a/addons/test_mail/tests/test_mail_resend.py +++ b/addons/test_mail/tests/test_message_management.py @@ -1,130 +1,157 @@ -# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-import itertools
-from unittest.mock import patch
-
-from odoo import api
-from odoo.addons.base.models.ir_mail_server import IrMailServer
-from odoo.addons.test_mail.tests import common
-from odoo.addons.test_mail.tests.common import mail_new_test_user
-from odoo.tests import tagged
-from odoo.tools import mute_logger
-
-
-@tagged('resend_test')
-class TestMailResend(common.BaseFunctionalTest, common.MockEmails):
-
- @classmethod
- def setUpClass(cls):
- super(TestMailResend, cls).setUpClass()
- #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({
- 'name': 'Partner 1',
- 'email': 'p1' # invalid email
- })
- cls.partner2 = cls.env['res.partner'].with_context(common.BaseFunctionalTest._test_context).create({
- 'name': 'Partner 2',
- 'email': 'p2@example.com'
- })
-
- @api.model
- def send_email(self, message, *args, **kwargs):
- assert '@' in message['To'], self.NO_VALID_RECIPIENT
- return message['Message-Id']
- cls.bus_update_failure = []
- def sendone(self, channel, message):
- if 'type' in message and message['type'] == 'mail_failure':
- cls.bus_update_failure.append((channel, message))
- cls.env['ir.mail_server']._patch_method('send_email', send_email)
- cls.env['bus.bus']._patch_method('sendone', sendone)
- cls.partners = cls.env['res.partner'].concat(cls.user1.partner_id, cls.user2.partner_id, cls.partner1, cls.partner2)
- cls.invalid_email_partners = cls.env['res.partner'].concat(cls.user1.partner_id, cls.partner1)
-
- def setUp(self):
- super(TestMailResend, self).setUp()
- TestMailResend.bus_update_failure = []
-
- def assertNotifStates(self, states, message):
- notif = self.env['mail.notification'].search([('mail_message_id', '=', message.id)], order="res_partner_id asc")
- self.assertEquals(tuple(notif.mapped('notification_status')), states)
- return notif
-
- def assertBusMessage(self, partners):
- partner_ids = [elem[0][2] for elem in self.bus_update_failure]
- self.assertEquals(partner_ids, [partner.id for partner in partners])
- self.bus_update_failure.clear()
-
- @classmethod
- def tearDownClass(cls):
- # Remove mocks
- cls.env['ir.mail_server']._revert_method('send_email')
- cls.env['bus.bus']._revert_method('sendone')
- super(TestMailResend, cls).tearDownClass()
-
- def assertEmails(self, *args, **kwargs):
- res = super(TestMailResend, self).assertEmails(*args, **kwargs)
- self._mails.clear()
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_mail_resend_workflow(self):
- cls = TestMailResend
- #missconfigured server
- @api.model
- def connect_failure(**kwargs):
- raise Exception
- with patch.object(IrMailServer, 'connect', side_effect=connect_failure):
- message = self.test_record.with_user(self.user_admin).message_post(partner_ids=self.partners.ids, subtype='mail.mt_comment', message_type='notification')
- self.assertBusMessage([self.partner_admin])
- self.assertEmails(self.partner_admin, [])
- self.assertNotifStates(('exception', 'exception', 'exception', 'exception'), message)
- wizard = self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({})
- self.assertEqual(wizard.notification_ids.mapped('res_partner_id'), self.partners, "wizard should manage notifications for each failed partner")
- wizard.resend_mail_action()
- self.assertBusMessage([self.partner_admin] * 3) # three more failure sent on bus, one for each mail in failure and one for resend
- self.assertEmails(self.partner_admin, self.partners)
- self.assertNotifStates(('exception', 'sent', 'exception', 'sent'), message)
- self.user1.write({"email": 'u1@example.com'})
- self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({}).resend_mail_action()
- self.assertBusMessage([self.partner_admin] * 2) # two more failure update sent on bus, one for failed mail and one for resend
- self.assertEmails(self.partner_admin, self.invalid_email_partners)
- self.assertNotifStates(('sent', 'sent', 'exception', 'sent'), message)
- self.partner1.write({"email": 'p1@example.com'})
- self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({}).resend_mail_action()
- self.assertBusMessage([self.partner_admin]) # A success update should be sent on bus once the email has no more failure
- self.assertEmails(self.partner_admin, self.partner1)
- self.assertNotifStates(('sent', 'sent', 'sent', 'sent'), message)
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_mail_send_no_failure(self):
- self.user1.write({"email": 'u1@example.com'})
- self.partner1.write({"email": 'p1@example.com'})
- message = self.test_record.with_user(self.user_admin).message_post(partner_ids=self.partners.ids, subtype='mail.mt_comment', message_type='notification')
- self.assertBusMessage([]) # one update for cancell
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_remove_mail_become_canceled(self):
- message = self.test_record.with_user(self.user_admin).message_post(partner_ids=self.partners.ids, subtype='mail.mt_comment', message_type='notification')
- self.assertEmails(self.partner_admin, self.partners)
- self.assertBusMessage([self.partner_admin] * 2) # two failure sent on bus, one for each mail
- wizard = self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({})
- partners = wizard.partner_ids.mapped("partner_id")
- self.assertEqual(self.invalid_email_partners, partners)
- wizard.partner_ids.filtered(lambda p: p.partner_id == self.partner1).write({"resend": False})
- wizard.resend_mail_action()
- self.assertEmails(self.partner_admin, self.user1)
- self.assertBusMessage([self.partner_admin] * 2) # two more failure sent on bus, one for failure, one for resend
- self.assertNotifStates(('exception', 'sent', 'canceled', 'sent'), message)
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_cancel_all(self):
- message = self.test_record.with_user(self.user_admin).message_post(partner_ids=self.partners.ids, subtype='mail.mt_comment', message_type='notification')
- self.assertNotifStates(('exception', 'sent', 'exception', 'sent'), message)
- self.assertBusMessage([self.partner_admin] * 2)
- wizard = self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({})
- wizard.cancel_mail_action()
- self.assertNotifStates(('canceled', 'sent', 'canceled', 'sent'), message)
- self.assertBusMessage([self.partner_admin]) # one update for cancell
+# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from unittest.mock import patch + +from odoo import api +from odoo.addons.base.models.ir_mail_server import IrMailServer +from odoo.addons.test_mail.tests import common +from odoo.addons.test_mail.tests.common import mail_new_test_user +from odoo.tests import tagged +from odoo.tools import mute_logger + + +@tagged('mail_wizards') +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(cls._test_context).create({ + 'name': 'Partner 1', + 'email': 'p1' # invalid email + }) + cls.partner2 = cls.env['res.partner'].with_context(cls._test_context).create({ + 'name': 'Partner 2', + 'email': 'p2@example.com' + }) + + @api.model + def send_email(self, message, *args, **kwargs): + assert '@' in message['To'], self.NO_VALID_RECIPIENT + return message['Message-Id'] + cls.bus_update_failure = [] + def sendone(self, channel, message): + if 'type' in message and message['type'] == 'mail_failure': + cls.bus_update_failure.append((channel, message)) + cls.env['ir.mail_server']._patch_method('send_email', send_email) + cls.env['bus.bus']._patch_method('sendone', sendone) + cls.partners = cls.env['res.partner'].concat(cls.user1.partner_id, cls.user2.partner_id, cls.partner1, cls.partner2) + cls.invalid_email_partners = cls.env['res.partner'].concat(cls.user1.partner_id, cls.partner1) + + def setUp(self): + super(TestMailResend, self).setUp() + TestMailResend.bus_update_failure = [] + + def assertPartnerNotif(self, partner, state, message): + # TDE CLEANME: quick fix, should be cleaned and moved to mail testing tools + notif = self.env['mail.notification'].search([ + ('res_partner_id', '=', partner.id), + ('mail_message_id', '=', message.id)] + ) + self.assertEquals(notif.notification_status, state) + return notif + + def assertBusMessage(self, partners): + partner_ids = [elem[0][2] for elem in self.bus_update_failure] + self.assertEquals(partner_ids, [partner.id for partner in partners]) + self.bus_update_failure.clear() + + @classmethod + def tearDownClass(cls): + # Remove mocks + cls.env['ir.mail_server']._revert_method('send_email') + cls.env['bus.bus']._revert_method('sendone') + super(TestMailResend, cls).tearDownClass() + + def assertEmails(self, *args, **kwargs): + res = super(TestMailResend, self).assertEmails(*args, **kwargs) + self._mails.clear() + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mail_resend_workflow(self): + cls = TestMailResend + #missconfigured server + @api.model + def connect_failure(**kwargs): + raise Exception + with patch.object(IrMailServer, 'connect', side_effect=connect_failure): + message = self.test_record.with_user(self.user_admin).message_post(partner_ids=self.partners.ids, subtype='mail.mt_comment', message_type='notification') + self.assertBusMessage([self.partner_admin]) + self.assertEmails(self.partner_admin, []) + for partner in [self.user1.partner_id, self.user2.partner_id, self.partner1, self.partner2]: + self.assertPartnerNotif(partner, 'exception', message) + + wizard = self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({}) + self.assertEqual(wizard.notification_ids.mapped('res_partner_id'), self.partners, "wizard should manage notifications for each failed partner") + wizard.resend_mail_action() + self.assertBusMessage([self.partner_admin] * 3) # three more failure sent on bus, one for each mail in failure and one for resend + self.assertEmails(self.partner_admin, self.partners) + for partner in [self.user1.partner_id, self.partner1]: + self.assertPartnerNotif(partner, 'exception', message) + for partner in [self.user2.partner_id, self.partner2]: + self.assertPartnerNotif(partner, 'sent', message) + + self.user1.write({"email": 'u1@example.com'}) + self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({}).resend_mail_action() + self.assertBusMessage([self.partner_admin] * 2) # two more failure update sent on bus, one for failed mail and one for resend + self.assertEmails(self.partner_admin, self.invalid_email_partners) + for partner in [self.partner1]: + self.assertPartnerNotif(partner, 'exception', message) + for partner in [self.user1.partner_id, self.user2.partner_id, self.partner2]: + self.assertPartnerNotif(partner, 'sent', message) + + self.partner1.write({"email": 'p1@example.com'}) + self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({}).resend_mail_action() + self.assertBusMessage([self.partner_admin]) # A success update should be sent on bus once the email has no more failure + self.assertEmails(self.partner_admin, self.partner1) + for partner in [self.user1.partner_id, self.user2.partner_id, self.partner1, self.partner2]: + self.assertPartnerNotif(partner, 'sent', message) + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mail_send_no_failure(self): + self.user1.write({"email": 'u1@example.com'}) + self.partner1.write({"email": 'p1@example.com'}) + message = self.test_record.with_user(self.user_admin).message_post(partner_ids=self.partners.ids, subtype='mail.mt_comment', message_type='notification') + self.assertBusMessage([]) # one update for cancell + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_remove_mail_become_canceled(self): + message = self.test_record.with_user(self.user_admin).message_post(partner_ids=self.partners.ids, subtype='mail.mt_comment', message_type='notification') + self.assertEmails(self.partner_admin, self.partners) + self.assertBusMessage([self.partner_admin] * 2) # two failure sent on bus, one for each mail + wizard = self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({}) + partners = wizard.partner_ids.mapped("partner_id") + self.assertEqual(self.invalid_email_partners, partners) + wizard.partner_ids.filtered(lambda p: p.partner_id == self.partner1).write({"resend": False}) + wizard.resend_mail_action() + self.assertEmails(self.partner_admin, self.user1) + self.assertBusMessage([self.partner_admin] * 2) # two more failure sent on bus, one for failure, one for resend + for partner in [self.user1.partner_id]: + self.assertPartnerNotif(partner, 'exception', message) + for partner in [self.partner1]: + self.assertPartnerNotif(partner, 'canceled', message) + for partner in [self.user2.partner_id, self.partner2]: + self.assertPartnerNotif(partner, 'sent', message) + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_cancel_all(self): + message = self.test_record.with_user(self.user_admin).message_post(partner_ids=self.partners.ids, subtype='mail.mt_comment', message_type='notification') + for partner in [self.user1.partner_id, self.partner1]: + self.assertPartnerNotif(partner, 'exception', message) + for partner in [self.user2.partner_id, self.partner2]: + self.assertPartnerNotif(partner, 'sent', message) + self.assertBusMessage([self.partner_admin] * 2) + wizard = self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({}) + wizard.cancel_mail_action() + for partner in [self.user1.partner_id, self.partner1]: + self.assertPartnerNotif(partner, 'canceled', message) + for partner in [self.user2.partner_id, self.partner2]: + self.assertPartnerNotif(partner, 'sent', message) + self.assertBusMessage([self.partner_admin]) # one update for cancell diff --git a/addons/test_mail/tests/test_message_compose.py b/addons/test_mail/tests/test_message_post.py index adf1dd80ae6..2eecfb98b9e 100644 --- a/addons/test_mail/tests/test_message_compose.py +++ b/addons/test_mail/tests/test_message_post.py @@ -7,26 +7,61 @@ from email.utils import formataddr from unittest.mock import patch from odoo.addons.test_mail.tests.common import BaseFunctionalTest, MockEmails, TestRecipients -from odoo.addons.test_mail.tests.common import mail_new_test_user from odoo.addons.test_mail.data.test_mail_data import MAIL_TEMPLATE_PLAINTEXT from odoo.addons.test_mail.models.test_mail_models import MailTestSimple from odoo.exceptions import AccessError from odoo.tools import mute_logger -class TestMessagePost(BaseFunctionalTest, MockEmails, TestRecipients): +class TestMessagePost(BaseFunctionalTest, TestRecipients, MockEmails): - def setUp(self): - super(TestMessagePost, self).setUp() + @classmethod + def setUpClass(cls): + super(TestMessagePost, cls).setUpClass() + cls._create_portal_user() + cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'}) # configure mailing - self.alias_domain = 'schlouby.fr' - self.alias_catchall = 'test+catchall' - self.env['ir.config_parameter'].set_param('mail.catchall.domain', self.alias_domain) - self.env['ir.config_parameter'].set_param('mail.catchall.alias', self.alias_catchall) + cls.alias_domain = 'schlouby.fr' + cls.alias_catchall = 'test+catchall' + cls.env['ir.config_parameter'].set_param('mail.catchall.domain', cls.alias_domain) + cls.env['ir.config_parameter'].set_param('mail.catchall.alias', cls.alias_catchall) - # admin should not receive emails - self.user_admin.write({'notification_type': 'email'}) + cls.user_admin.write({'notification_type': 'email'}) + + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_post_needaction(self): + (self.user_employee | self.user_admin).write({'notification_type': 'inbox'}) + with self.assertNotifications(partner_employee=(1, 'inbox', 'unread'), partner_admin=(0, '', '')): + self.test_record.message_post( + body='Test', message_type='comment', subtype='mail.mt_comment', + partner_ids=[self.user_employee.partner_id.id]) + + self.test_record.message_subscribe([self.partner_1.id]) + with self.assertNotifications(partner_employee=(1, 'inbox', 'unread'), partner_admin=(0, '', ''), partner_1=(1, 'email', 'read')): + self.test_record.message_post( + body='Test', message_type='comment', subtype='mail.mt_comment', + partner_ids=[self.user_employee.partner_id.id]) + + with self.assertNotifications(partner_admin=(0, '', ''), partner_1=(1, 'email', 'read'), partner_portal=(1, 'email', 'read')): + self.test_record.message_post( + body='Test', message_type='comment', subtype='mail.mt_comment', + partner_ids=[self.partner_portal.id]) + + def test_post_inactive_follower(self): + # In some case odoobot is follower of a record. + # Even if it shouldn't be the case, we want to be sure that odoobot is not notified + (self.user_employee | self.user_admin).write({'notification_type': 'inbox'}) + self.test_record._message_subscribe(self.user_employee.partner_id.ids) + with self.assertNotifications(partner_employee=(1, 'inbox', 'unread')): + self.test_record.message_post( + body='Test', message_type='comment', subtype='mail.mt_comment') + self.user_employee.active = False + # at this point, partner is still active and would receive an email notification + self.user_employee.partner_id._write({'active': False}) + with self.assertNotifications(partner_employee=(0, '', '')): + self.test_record.message_post( + body='Test', message_type='comment', subtype='mail.mt_comment') @mute_logger('odoo.addons.mail.models.mail_mail') def test_post_notifications(self): @@ -153,22 +188,18 @@ class TestMessagePost(BaseFunctionalTest, MockEmails, TestRecipients): @mute_logger('odoo.addons.mail.models.mail_mail') def test_post_portal_ok(self): - portal_user = mail_new_test_user(self.env, login='chell', groups='base.group_portal', name='Chell Gladys') - with patch.object(MailTestSimple, 'check_access_rights', return_value=True): self.test_record.message_subscribe((self.partner_1 | self.user_employee.partner_id).ids) - new_msg = self.test_record.with_user(portal_user).message_post( + new_msg = self.test_record.with_user(self.user_portal).message_post( body='<p>Test</p>', 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='<p>Test</p>', subject='Subject', message_type='comment', subtype='mt_comment') @@ -220,151 +251,43 @@ class TestMessagePost(BaseFunctionalTest, MockEmails, TestRecipients): self.assertNotIn(new_notification, self.test_record.message_ids) # todo xdo add test message_notify on thread with followers and stuff - -class TestComposer(BaseFunctionalTest, MockEmails, TestRecipients): - - def setUp(self): - super(TestComposer, self).setUp() - - # configure mailing - self.alias_domain = 'schlouby.fr' - self.alias_catchall = 'test+catchall' - self.env['ir.config_parameter'].set_param('mail.catchall.domain', self.alias_domain) - self.env['ir.config_parameter'].set_param('mail.catchall.alias', self.alias_catchall) - - # admin should not receive emails - self.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': '<p>Test Body</p>', - 'partner_ids': [(4, self.partner_1.id), (4, self.partner_2.id)] + 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)], }) - composer.send_mail() - - message = self.test_record.message_ids[0] - self.assertEqual(message.body, '<p>Test Body</p>') - 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': '<p>Mega</p>', - }).send_mail() - - message = self.test_record.message_ids[0] - self.assertEqual(message.body, '<p>Mega</p>') - self.assertEqual(message.parent_id, parent) - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_composer_mass_mail(self): - test_record_2 = self.env['mail.test.simple'].with_context(BaseFunctionalTest._test_context).create({'name': 'Test2'}) - - composer = self.env['mail.compose.message'].with_context({ - 'default_composition_mode': 'mass_mail', - 'default_model': self.test_record._name, - 'default_res_id': False, - 'active_ids': [self.test_record.id, test_record_2.id] - }).with_user(self.user_employee).create({ - 'subject': 'Testing ${object.name}', - 'body': '<p>${object.name}</p>', - 'partner_ids': [(4, self.partner_1.id), (4, self.partner_2.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, }) - 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, '<p>%s</p>' % 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, '<p>%s</p>' % test_record_2.name) - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_composer_mass_mail_active_domain(self): - test_record_2 = self.env['mail.test.simple'].with_context(BaseFunctionalTest._test_context).create({'name': 'Test2'}) - - self.env['mail.compose.message'].with_context({ - 'default_composition_mode': 'mass_mail', - 'default_model': self.test_record._name, - 'default_use_active_domain': True, - 'active_ids': [self.test_record.id], - 'active_domain': [('name', 'in', ['%s' % self.test_record.name, '%s' % test_record_2.name])], - }).with_user(self.user_employee).create({ - 'subject': 'From Composer Test', - 'body': '${object.name}', - }).send_mail() - - self.assertEqual(self.test_record.message_ids[0].subject, 'From Composer Test') - self.assertEqual(test_record_2.message_ids[0].subject, 'From Composer Test') - - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_message_compose_mass_mail_no_active_domain(self): - test_record_2 = self.env['mail.test.simple'].with_context(BaseFunctionalTest._test_context).create({'name': 'Test2'}) - - self.env['mail.compose.message'].with_context({ - 'default_composition_mode': 'mass_mail', - 'default_model': self.test_record._name, - 'default_use_active_domain': False, - 'active_ids': [self.test_record.id], - 'active_domain': [('name', 'in', ['%s' % self.test_record.name, '%s' % test_record_2.name])], - }).with_user(self.user_employee).create({ - 'subject': 'From Composer Test', - 'body': '${object.name}', - }).send_mail() - - self.assertEqual(self.test_record.message_ids[0].subject, 'From Composer Test') - self.assertFalse(test_record_2.message_ids.ids) + # admin should receive emails + self.user_admin.write({'notification_type': 'email'}) + # Force the attachments of the template to be in the natural order. + self.email_template.invalidate_cache(['attachment_ids'], ids=self.email_template.ids) - @mute_logger('odoo.addons.mail.models.mail_mail') - def test_message_compose_portal_ok(self): - portal_user = mail_new_test_user(self.env, login='chell', groups='base.group_portal', name='Chell Gladys') + test_record.with_user(self.user_employee).message_post_with_template(self.email_template.id, composition_mode='comment') - 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': '<p>Body text</p>', - 'partner_ids': []}).send_mail() - - self.assertEqual(self.test_record.message_ids[0].body, '<p>Body text</p>') - 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': '<p>Body text 2</p>'}).send_mail() - - self.assertEqual(self.test_record.message_ids[0].body, '<p>Body text 2</p>') - self.assertEqual(self.test_record.message_ids[0].author_id, portal_user.partner_id) + new_partners = self.env['res.partner'].search([('email', 'in', [email_1, email_2])]) + self.assertEmails( + self.user_employee.partner_id, + [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]], + subject='About %s' % test_record.name, + body_content=test_record.name, + attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')]) diff --git a/addons/test_mail/tests/test_message_track.py b/addons/test_mail/tests/test_message_track.py index 49d5df613ab..2771e7b8d45 100644 --- a/addons/test_mail/tests/test_message_track.py +++ b/addons/test_mail/tests/test_message_track.py @@ -1,32 +1,17 @@ # -*- coding: utf-8 -*- from email.utils import formataddr +from unittest.mock import patch from odoo.addons.test_mail.tests import common class TestTracking(common.BaseFunctionalTest, common.MockEmails): - def assertTracking(self, message, data): - tracking_values = message.sudo().tracking_value_ids - for field_name, value_type, old_value, new_value in data: - tracking = tracking_values.filtered(lambda track: track.field == field_name) - self.assertEqual(len(tracking), 1) - if value_type in ('char', 'integer'): - self.assertEqual(tracking.old_value_char, old_value) - self.assertEqual(tracking.new_value_char, new_value) - elif value_type in ('many2one'): - self.assertEqual(tracking.old_value_integer, old_value and old_value.id or False) - self.assertEqual(tracking.new_value_integer, new_value and new_value.id or False) - self.assertEqual(tracking.old_value_char, old_value and old_value.display_name or '') - self.assertEqual(tracking.new_value_char, new_value and new_value.display_name or '') - else: - self.assertEqual(1, 0) - def setUp(self): super(TestTracking, self).setUp() - record = self.env['mail.test.full'].with_user(self.user_employee).with_context(common.BaseFunctionalTest._test_context).create({ + record = self.env['mail.test.full'].with_user(self.user_employee).with_context(self._test_context).create({ 'name': 'Test', }) self.record = record.with_context(mail_notrack=False) @@ -120,7 +105,7 @@ class TestTracking(common.BaseFunctionalTest, common.MockEmails): def test_message_track_template_at_create(self): """ Create a record with tracking template on create, template should be sent.""" - Model = self.env['mail.test.full'].with_user(self.user_employee).with_context(common.BaseFunctionalTest._test_context) + Model = self.env['mail.test.full'].with_user(self.user_employee).with_context(self._test_context) Model = Model.with_context(mail_notrack=False) record = Model.create({ 'name': 'Test', @@ -185,3 +170,37 @@ class TestTracking(common.BaseFunctionalTest, common.MockEmails): ('name', '=', 'email_from')]) ir_model_field.with_context(_force_unlink=True).unlink() self.assertEqual(len(record_sudo.message_ids.tracking_value_ids), 0) + + def test_create_partner_from_tracking_multicompany(self): + company1 = self.env['res.company'].create({'name': 'company1'}) + self.env.user.write({'company_ids': [(4, company1.id, False)]}) + self.assertNotEqual(self.env.company, company1) + + email_new_partner = "diamonds@rust.com" + Partner = self.env['res.partner'] + self.assertFalse(Partner.search([('email', '=', email_new_partner)])) + + template = self.env['mail.template'].create({ + 'model_id': self.env['ir.model']._get('mail.test.track').id, + 'name': 'AutoTemplate', + 'subject': 'autoresponse', + 'email_from': self.env.user.email_formatted, + 'email_to': "${object.email_from}", + 'body_html': "<div>A nice body</div>", + }) + + 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_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 = '<a href="http://odoo.com/web#model=res.partner&id=%s" class="o_mail_redirect" data-oe-id="%s" data-oe-model="res.partner" target="_blank">@OdooBot</a>' % (self.odoobot.id, self.odoobot.id) - self.test_record_employe = self.test_record.with_user(self.user_employee) + cls.odoobot_ping_body = '<a href="http://odoo.com/web#model=res.partner&id=%s" class="o_mail_redirect" data-oe-id="%s" data-oe-model="res.partner" target="_blank">@OdooBot</a>' % (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): diff --git a/addons/test_mail/tests/test_performance.py b/addons/test_mail/tests/test_performance.py index 9064cedb812..919d6ac9dd7 100644 --- a/addons/test_mail/tests/test_performance.py +++ b/addons/test_mail/tests/test_performance.py @@ -65,7 +65,7 @@ class TestMailPerformance(BaseMailPerformance): records = self.env['test_performance.mail'].search([]) self.assertEqual(len(records), 5) - with self.assertQueryCount(__system__=3, demo=3): # test_mail only: 3 - 3 + with self.assertQueryCount(__system__=3, demo=3): records.write({'name': 'X'}) @users('__system__', 'demo') @@ -75,7 +75,7 @@ class TestMailPerformance(BaseMailPerformance): records = self.env['test_performance.mail'].search([]) self.assertEqual(len(records), 5) - with self.assertQueryCount(__system__=5, demo=5): # test_mail only: 5 - 5 + with self.assertQueryCount(__system__=3, demo=3): records.write({'value': 42}) @users('__system__', 'demo') @@ -89,7 +89,7 @@ class TestMailPerformance(BaseMailPerformance): 'partner_id': self.env.ref('base.res_partner_12').id, }) - with self.assertQueryCount(__system__=4, demo=4): # test_mail only: 4 - 4 + with self.assertQueryCount(__system__=3, demo=3): record.track = 'X' @users('__system__', 'demo') @@ -98,27 +98,27 @@ class TestMailPerformance(BaseMailPerformance): """ Create records inheriting from 'mail.thread' (without field tracking). """ model = self.env['test_performance.mail'] - with self.assertQueryCount(__system__=3, demo=3): # test_mail only: 3 - 3 + with self.assertQueryCount(__system__=2, demo=2): model.with_context(tracking_disable=True).create({'name': 'X'}) @users('__system__', 'demo') @warmup def test_create_mail_with_tracking(self): """ Create records inheriting from 'mail.thread' (with field tracking). """ - with self.assertQueryCount(__system__=8, demo=8): # test_mail only: 8 - 8 + with self.assertQueryCount(__system__=7, demo=7): self.env['test_performance.mail'].create({'name': 'X'}) @users('__system__', 'emp') @warmup def test_create_mail_simple(self): - with self.assertQueryCount(__system__=6, emp=6): # test_mail only: 6 - 6 + with self.assertQueryCount(__system__=6, emp=6): self.env['mail.test.simple'].create({'name': 'Test'}) @users('__system__', 'emp') @warmup def test_write_mail_simple(self): rec = self.env['mail.test.simple'].create({'name': 'Test'}) - with self.assertQueryCount(__system__=1, emp=1): # test_mail only: 1 - 1 + with self.assertQueryCount(__system__=1, emp=1): rec.write({ 'name': 'Test2', 'email_from': 'test@test.com', @@ -150,7 +150,7 @@ class TestAdvMailPerformance(BaseMailPerformance): def test_adv_activity(self): model = self.env['mail.test.activity'] - with self.assertQueryCount(__system__=7, emp=6): # test_mail only: 7 - 6 + with self.assertQueryCount(__system__=6, emp=6): model.create({'name': 'Test'}) @users('__system__', 'emp') @@ -162,7 +162,7 @@ class TestAdvMailPerformance(BaseMailPerformance): 'default_res_model': 'mail.test.activity', }) - with self.assertQueryCount(__system__=10, emp=13): # com runbot: 10 - 13 // test_mail only: 10 - 13 + with self.assertQueryCount(__system__=6, emp=6): activity = MailActivity.create({ 'summary': 'Test Activity', 'res_id': record.id, @@ -172,7 +172,7 @@ class TestAdvMailPerformance(BaseMailPerformance): #voip module read activity_type during create leading to one less query in enterprise on action_feedback category = activity.activity_type_id.category - with self.assertQueryCount(__system__=24, emp=31): # com runbot: 24 - 31 // test_mail only: 24 - 31 + with self.assertQueryCount(__system__=19, emp=22): activity.action_feedback(feedback='Zizisse Done !') @users('__system__', 'emp') @@ -181,7 +181,7 @@ class TestAdvMailPerformance(BaseMailPerformance): def test_adv_activity_mixin(self): record = self.env['mail.test.activity'].create({'name': 'Test'}) - with self.assertQueryCount(__system__=10, emp=14): # com runbot: 10 - 14 // test_mail only: 10 - 14 + with self.assertQueryCount(__system__=7, emp=7): activity = record.action_start('Test Start') #read activity_type to normalize cache between enterprise and community #voip module read activity_type during create leading to one less query in enterprise on action_close @@ -189,7 +189,7 @@ class TestAdvMailPerformance(BaseMailPerformance): record.write({'name': 'Dupe write'}) - with self.assertQueryCount(__system__=26, emp=31): # com runbot: 26 - 31 // test_mail only: 26 - 31 + with self.assertQueryCount(__system__=20, emp=22): record.action_close('Dupe feedback') self.assertEqual(record.activity_ids, self.env['mail.activity']) @@ -200,7 +200,7 @@ class TestAdvMailPerformance(BaseMailPerformance): def test_message_assignation_email(self): self.user_test.write({'notification_type': 'email'}) record = self.env['mail.test.track'].create({'name': 'Test'}) - with self.assertQueryCount(__system__=52, emp=54): # com runbot: 52 - 54 // test_mail only: 52 - 54 + with self.assertQueryCount(__system__=39, emp=40): record.write({ 'user_id': self.user_test.id, }) @@ -209,7 +209,7 @@ class TestAdvMailPerformance(BaseMailPerformance): @warmup def test_message_assignation_inbox(self): record = self.env['mail.test.track'].create({'name': 'Test'}) - with self.assertQueryCount(__system__=32, emp=37): # test_mail only: 32 - 37 + with self.assertQueryCount(__system__=27, emp=29): record.write({ 'user_id': self.user_test.id, }) @@ -219,7 +219,7 @@ class TestAdvMailPerformance(BaseMailPerformance): def test_message_log(self): record = self.env['mail.test.simple'].create({'name': 'Test'}) - with self.assertQueryCount(__system__=1, emp=1): # test_mail only: 1 - 1 + with self.assertQueryCount(__system__=1, emp=1): record._message_log( body='<p>Test _message_log</p>', message_type='comment') @@ -229,7 +229,7 @@ class TestAdvMailPerformance(BaseMailPerformance): def test_message_log_with_post(self): record = self.env['mail.test.simple'].create({'name': 'Test'}) - with self.assertQueryCount(__system__=6, emp=7): # test_mail only: 6 - 7 + with self.assertQueryCount(__system__=5, emp=6): record.message_post( body='<p>Test message_post as log</p>', subtype='mail.mt_note', @@ -240,7 +240,7 @@ class TestAdvMailPerformance(BaseMailPerformance): def test_message_post_no_notification(self): record = self.env['mail.test.simple'].create({'name': 'Test'}) - with self.assertQueryCount(__system__=6, emp=7): # test_mail only: 6 - 7 + with self.assertQueryCount(__system__=5, emp=6): record.message_post( body='<p>Test Post Performances basic</p>', partner_ids=[], @@ -253,7 +253,7 @@ class TestAdvMailPerformance(BaseMailPerformance): def test_message_post_one_email_notification(self): record = self.env['mail.test.simple'].create({'name': 'Test'}) - with self.assertQueryCount(__system__=44, emp=47): # com runbot: 44 - 47 // test_mail only: 44 - 47 + with self.assertQueryCount(__system__=32, emp=33): record.message_post( body='<p>Test Post Performances with an email ping</p>', partner_ids=self.customer.ids, @@ -265,7 +265,7 @@ class TestAdvMailPerformance(BaseMailPerformance): def test_message_post_one_inbox_notification(self): record = self.env['mail.test.simple'].create({'name': 'Test'}) - with self.assertQueryCount(__system__=29, emp=34): # com runbot 29 - 34 // test_mail only: 29 - 34 + with self.assertQueryCount(__system__=23, emp=25): record.message_post( body='<p>Test Post Performances with an inbox ping</p>', partner_ids=self.user_test.partner_id.ids, @@ -278,10 +278,10 @@ class TestAdvMailPerformance(BaseMailPerformance): def test_message_subscribe_default(self): record = self.env['mail.test.simple'].create({'name': 'Test'}) - with self.assertQueryCount(__system__=6, emp=6): # test_mail only: 6 - 6 + with self.assertQueryCount(__system__=6, emp=6): record.message_subscribe(partner_ids=self.user_test.partner_id.ids) - with self.assertQueryCount(__system__=3, emp=3): # test_mail only: 3 - 3 + with self.assertQueryCount(__system__=3, emp=3): record.message_subscribe(partner_ids=self.user_test.partner_id.ids) @mute_logger('odoo.models.unlink') @@ -291,10 +291,10 @@ class TestAdvMailPerformance(BaseMailPerformance): record = self.env['mail.test.simple'].create({'name': 'Test'}) subtype_ids = (self.env.ref('test_mail.st_mail_test_simple_external') | self.env.ref('mail.mt_comment')).ids - with self.assertQueryCount(__system__=5, emp=5): # test_mail only: 5 - 5 + with self.assertQueryCount(__system__=5, emp=5): record.message_subscribe(partner_ids=self.user_test.partner_id.ids, subtype_ids=subtype_ids) - with self.assertQueryCount(__system__=2, emp=2): # test_mail only: 2 - 2 + with self.assertQueryCount(__system__=2, emp=2): record.message_subscribe(partner_ids=self.user_test.partner_id.ids, subtype_ids=subtype_ids) @@ -362,7 +362,7 @@ class TestHeavyMailPerformance(BaseMailPerformance): 'recipient_ids': [(4, pid) for pid in self.partners.ids], }) mail_ids = mail.ids - with self.assertQueryCount(__system__=16, emp=21): # test_mail only: 16 - 21 + with self.assertQueryCount(__system__=7, emp=7): self.env['mail.mail'].browse(mail_ids).send() self.assertEqual(mail.body_html, '<p>Test</p>') @@ -375,7 +375,7 @@ class TestHeavyMailPerformance(BaseMailPerformance): self.umbrella.message_subscribe(self.user_portal.partner_id.ids) record = self.umbrella.with_user(self.env.user) - with self.assertQueryCount(__system__=82, emp=85): # com runbot: 82 - 85 // test_mail only: 82 - 85 + with self.assertQueryCount(__system__=71, emp=72): record.message_post( body='<p>Test Post Performances</p>', message_type='comment', @@ -392,7 +392,7 @@ class TestHeavyMailPerformance(BaseMailPerformance): record = self.umbrella.with_user(self.env.user) template_id = self.env.ref('test_mail.mail_test_tpl').id - with self.assertQueryCount(__system__=98, emp=103): # com runbot: 98 - 103 // test_mail only: 98 - 103 + with self.assertQueryCount(__system__=81, emp=82): record.message_post_with_template(template_id, message_type='comment', composition_mode='comment') self.assertEqual(record.message_ids[0].body, '<p>Adding stuff on %s</p>' % record.name) @@ -417,7 +417,7 @@ class TestHeavyMailPerformance(BaseMailPerformance): self.assertEqual(rec.message_channel_ids, self.env['mail.channel']) # subscribe new followers with forced given subtypes - with self.assertQueryCount(__system__=8, emp=8): # test_mail only: 8 - 8 + with self.assertQueryCount(__system__=8, emp=8): rec.message_subscribe( partner_ids=pids[:4], channel_ids=cids, @@ -428,7 +428,7 @@ class TestHeavyMailPerformance(BaseMailPerformance): self.assertEqual(rec.message_channel_ids, self.channel) # subscribe existing and new followers with force=False, meaning only some new followers will be added - with self.assertQueryCount(__system__=6, emp=6): # test_mail only: 6 - 6 + with self.assertQueryCount(__system__=6, emp=6): rec.message_subscribe( partner_ids=pids[:6], channel_ids=cids, @@ -439,7 +439,7 @@ class TestHeavyMailPerformance(BaseMailPerformance): self.assertEqual(rec.message_channel_ids, self.channel) # subscribe existing and new followers with force=True, meaning all will have the same subtypes - with self.assertQueryCount(__system__=7, emp=7): # test_mail only: 7 - 7 + with self.assertQueryCount(__system__=7, emp=7): rec.message_subscribe( partner_ids=pids, channel_ids=cids, @@ -461,7 +461,7 @@ class TestHeavyMailPerformance(BaseMailPerformance): 'user_id': self.env.uid, }) self.assertEqual(rec.message_partner_ids, self.partners | self.env.user.partner_id) - with self.assertQueryCount(__system__=52, emp=53): # com runbot: 51 - 53 // test_mail only: 51 - 53 + with self.assertQueryCount(__system__=39, emp=40): rec.write({'user_id': self.user_portal.id}) self.assertEqual(rec.message_partner_ids, self.partners | self.env.user.partner_id | self.user_portal.partner_id) # write tracking message @@ -481,7 +481,7 @@ class TestHeavyMailPerformance(BaseMailPerformance): customer_id = self.customer.id user_id = self.user_portal.id - with self.assertQueryCount(__system__=146, emp=149): # com runbot: 146 - 149 // test_mail only: 146 - 149 + with self.assertQueryCount(__system__=121, emp=122): rec = self.env['mail.test.full'].create({ 'name': 'Test', 'umbrella_id': umbrella_id, @@ -508,7 +508,7 @@ class TestHeavyMailPerformance(BaseMailPerformance): }) self.assertEqual(rec.message_partner_ids, self.user_portal.partner_id | self.env.user.partner_id) self.assertEqual(len(rec.message_ids), 1) - with self.assertQueryCount(__system__=100, emp=106): # com runbot: 100 -106 // test_mail only: 100 - 106 + with self.assertQueryCount(__system__=84, emp=85): rec.write({ 'name': 'Test2', 'umbrella_id': self.umbrella.id, @@ -544,7 +544,7 @@ class TestHeavyMailPerformance(BaseMailPerformance): }) self.assertEqual(rec.message_partner_ids, self.user_portal.partner_id | self.env.user.partner_id) - with self.assertQueryCount(__system__=105, emp=111): # test_mail only: 105 - 111 + with self.assertQueryCount(__system__=92, emp=93): rec.write({ 'name': 'Test2', 'umbrella_id': umbrella_id, @@ -576,7 +576,7 @@ class TestHeavyMailPerformance(BaseMailPerformance): }) self.assertEqual(rec.message_partner_ids, self.partners | self.env.user.partner_id | self.user_portal.partner_id) - with self.assertQueryCount(__system__=50, emp=63): # test_mail only: 50 - 63 + with self.assertQueryCount(__system__=33, emp=35): rec.write({ 'name': 'Test2', 'customer_id': customer_id, @@ -713,7 +713,7 @@ class TestMailPerformancePost(BaseMailPerformance): ] self.attachements = self.env['ir.attachment'].with_user(self.env.user).create(self.vals) attachement_ids = self.attachements.ids - with self.assertQueryCount(emp=175): # com runbot 154 // test_mail only: 132 + with self.assertQueryCount(emp=118): # runbot 118 // test_mail only: 110 self.cr.sql_log = self.warm and self.cr.sql_log_count record.with_context({}).message_post( body='<p>Test body <img src="cid:cid1"> <img src="cid:cid2"></p>', 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) |
