summaryrefslogtreecommitdiff
path: root/addons/test_mail/tests
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2019-09-13 18:07:59 +0200
committerChristophe Simonis <chs@odoo.com>2019-09-13 18:07:59 +0200
commit6c948c36bbf72dd896e0bff03aa7fbddadcbb0cd (patch)
treef8620905c011735d8a3c340c46d1417a54a75972 /addons/test_mail/tests
parent48503fcf08eac6fed12e080d4f501f9bbc8d257d (diff)
parent197474e5b9ad43ab2d587a98136a1a809ce9a2e7 (diff)
[MERGE] forward port branch saas-12.5 up to 197474e5b9a
Diffstat (limited to 'addons/test_mail/tests')
-rw-r--r--addons/test_mail/tests/__init__.py20
-rw-r--r--addons/test_mail/tests/common.py51
-rw-r--r--addons/test_mail/tests/test_discuss.py89
-rw-r--r--addons/test_mail/tests/test_invite.py9
-rw-r--r--addons/test_mail/tests/test_ir_actions.py15
-rw-r--r--addons/test_mail/tests/test_mail_activity.py29
-rw-r--r--addons/test_mail/tests/test_mail_cc.py63
-rw-r--r--addons/test_mail/tests/test_mail_channel.py29
-rw-r--r--addons/test_mail/tests/test_mail_followers.py26
-rw-r--r--addons/test_mail/tests/test_mail_gateway.py58
-rw-r--r--addons/test_mail/tests/test_mail_mail.py83
-rw-r--r--addons/test_mail/tests/test_mail_message.py115
-rw-r--r--addons/test_mail/tests/test_mail_race.py73
-rw-r--r--addons/test_mail/tests/test_mail_redirect.py (renamed from addons/test_mail/tests/test_multi_company.py)0
-rw-r--r--addons/test_mail/tests/test_mail_template.py215
-rw-r--r--addons/test_mail/tests/test_message_composer.py321
-rw-r--r--addons/test_mail/tests/test_message_management.py (renamed from addons/test_mail/tests/test_mail_resend.py)287
-rw-r--r--addons/test_mail/tests/test_message_post.py (renamed from addons/test_mail/tests/test_message_compose.py)243
-rw-r--r--addons/test_mail/tests/test_message_track.py55
-rw-r--r--addons/test_mail/tests/test_odoobot.py15
-rw-r--r--addons/test_mail/tests/test_performance.py70
-rw-r--r--addons/test_mail/tests/test_res_users.py34
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&amp;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&amp;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)