[MERGE] (test_)mail(_full): cleanup composer and post tests, add portal / rating
PURPOSE Cleanup and improve test coverage in test_mail(_full), notably about composer, message_post API (and its sub-methods) and attachments management. SPECIFICATIONS Improve tooling of mail tests. Use SMTP mockup class available in base tests in mail tests to have a better and simplified mock tool when dealing with mail tests. Remove old fashioned code. Add tests related to mail failure management and its effect on mail.mail and related mail.notification records. Cleanup and improve composer-related tests. As composer will soon be improved better ensure we don't break flows. Cleanup and improve post-related tests. As composer and posting methods will soon be improved better ensure we don't break flows. Add some first tests about rating and rating mixin: * rating preparation: token, information from the record to rate; * rating apply: posting message, author; See sub commits for more details. LINKS Task-2673913 (TestMail: Cleanup and improve test coverage) Task-2704390 (TestMailFull: add first rating tests) Prepares Task-2088884 (Mail: Composer Onchange to Editable Computed Stored) Prepares Task-2710804 (Mail: Clean MailThread API) Prepares Task-2684479 (Mail: Better send errors management) Prepares Task-36879 (Mail: Support MultiCompany Aliases) closes odoo/odoo#86393 Related: odoo/enterprise#25267 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -472,20 +472,20 @@ class MailActivity(models.Model):
|
||||
def action_done(self):
|
||||
""" Wrapper without feedback because web button add context as
|
||||
parameter, therefore setting context to feedback """
|
||||
messages, next_activities = self._action_done()
|
||||
return messages.ids and messages.ids[0] or False
|
||||
return self.action_feedback()
|
||||
|
||||
def action_feedback(self, feedback=False, attachment_ids=None):
|
||||
self = self.with_context(clean_context(self.env.context))
|
||||
messages, next_activities = self._action_done(feedback=feedback, attachment_ids=attachment_ids)
|
||||
return messages.ids and messages.ids[0] or False
|
||||
messages, _next_activities = self.with_context(
|
||||
clean_context(self.env.context)
|
||||
)._action_done(feedback=feedback, attachment_ids=attachment_ids)
|
||||
return messages[0].id if messages else False
|
||||
|
||||
def action_done_schedule_next(self):
|
||||
""" Wrapper without feedback because web button add context as
|
||||
parameter, therefore setting context to feedback """
|
||||
return self.action_feedback_schedule_next()
|
||||
|
||||
def action_feedback_schedule_next(self, feedback=False):
|
||||
def action_feedback_schedule_next(self, feedback=False, attachment_ids=None):
|
||||
ctx = dict(
|
||||
clean_context(self.env.context),
|
||||
default_previous_activity_type_id=self.activity_type_id.id,
|
||||
@@ -493,7 +493,7 @@ class MailActivity(models.Model):
|
||||
default_res_id=self.res_id,
|
||||
default_res_model=self.res_model,
|
||||
)
|
||||
messages, next_activities = self._action_done(feedback=feedback) # will unlink activity, dont access self after that
|
||||
_messages, next_activities = self._action_done(feedback=feedback, attachment_ids=attachment_ids) # will unlink activity, dont access self after that
|
||||
if next_activities:
|
||||
return False
|
||||
return {
|
||||
|
||||
@@ -475,7 +475,7 @@ class MailActivityMixin(models.AbstractModel):
|
||||
activities.write(write_vals)
|
||||
return activities
|
||||
|
||||
def activity_feedback(self, act_type_xmlids, user_id=None, feedback=None):
|
||||
def activity_feedback(self, act_type_xmlids, user_id=None, feedback=None, attachment_ids=None):
|
||||
""" Set activities as done, limiting to some activity types and
|
||||
optionally to a given user. """
|
||||
if self.env.context.get('mail_activity_automation_skip'):
|
||||
@@ -488,7 +488,7 @@ class MailActivityMixin(models.AbstractModel):
|
||||
return False
|
||||
activities = self.activity_search(act_type_xmlids, user_id=user_id)
|
||||
if activities:
|
||||
activities.action_feedback(feedback=feedback)
|
||||
activities.action_feedback(feedback=feedback, attachment_ids=attachment_ids)
|
||||
return True
|
||||
|
||||
def activity_unlink(self, act_type_xmlids, user_id=None):
|
||||
|
||||
+106
-59
@@ -11,10 +11,9 @@ from contextlib import contextmanager
|
||||
from functools import partial
|
||||
from lxml import html
|
||||
from unittest.mock import patch
|
||||
from smtplib import SMTPServerDisconnected
|
||||
|
||||
from odoo import exceptions
|
||||
from odoo.addons.base.models.ir_mail_server import IrMailServer, MailDeliveryException
|
||||
from odoo.addons.base.models.ir_mail_server import IrMailServer
|
||||
from odoo.addons.base.tests.common import MockSmtplibCase
|
||||
from odoo.addons.bus.models.bus import ImBus, json_dump
|
||||
from odoo.addons.mail.models.mail_mail import MailMail
|
||||
from odoo.addons.mail.models.mail_message import Message
|
||||
@@ -22,10 +21,14 @@ from odoo.addons.mail.models.mail_notification import MailNotification
|
||||
from odoo.tests import common, new_test_user
|
||||
from odoo.tools import formataddr, pycompat
|
||||
|
||||
mail_new_test_user = partial(new_test_user, context={'mail_create_nolog': True, 'mail_create_nosubscribe': True, 'mail_notrack': True, 'no_reset_password': True})
|
||||
mail_new_test_user = partial(new_test_user, context={'mail_create_nolog': True,
|
||||
'mail_create_nosubscribe': True,
|
||||
'mail_notrack': True,
|
||||
'no_reset_password': True,
|
||||
'mail_channel_nosubscribe': True})
|
||||
|
||||
|
||||
class MockEmail(common.BaseCase):
|
||||
class MockEmail(common.BaseCase, MockSmtplibCase):
|
||||
""" Tools, helpers and asserts for mailgateway-related tests
|
||||
|
||||
Useful reminders
|
||||
@@ -39,37 +42,19 @@ class MockEmail(common.BaseCase):
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@contextmanager
|
||||
def mock_mail_gateway(self, mail_unlink_sent=False, sim_error=None):
|
||||
def mock_mail_gateway(self, mail_unlink_sent=False):
|
||||
build_email_origin = IrMailServer.build_email
|
||||
send_email_origin = IrMailServer.send_email
|
||||
mail_create_origin = MailMail.create
|
||||
mail_unlink_origin = MailMail.unlink
|
||||
self.mail_unlink_sent = mail_unlink_sent
|
||||
self._init_mail_mock()
|
||||
|
||||
def _ir_mail_server_connect(model, *args, **kwargs):
|
||||
if sim_error and sim_error == 'connect_smtp_notfound':
|
||||
raise exceptions.UserError(
|
||||
"Missing SMTP Server\nPlease define at least one SMTP server, or provide the SMTP parameters explicitly.")
|
||||
if sim_error and sim_error == 'connect_failure':
|
||||
raise Exception("Some exception")
|
||||
return None
|
||||
|
||||
def _ir_mail_server_build_email(model, *args, **kwargs):
|
||||
self._mails.append(kwargs)
|
||||
self._mails_args.append(args)
|
||||
return build_email_origin(model, *args, **kwargs)
|
||||
|
||||
def _ir_mail_server_send_email(model, message, *args, **kwargs):
|
||||
if '@' not in message['To']:
|
||||
raise AssertionError(model.NO_VALID_RECIPIENT)
|
||||
if sim_error and sim_error == 'send_assert':
|
||||
raise AssertionError('AssertionError')
|
||||
elif sim_error and sim_error == 'send_disconnect':
|
||||
raise SMTPServerDisconnected('SMTPServerDisconnected')
|
||||
elif sim_error and sim_error == 'send_delivery':
|
||||
raise MailDeliveryException('MailDeliveryException')
|
||||
return message['Message-Id']
|
||||
|
||||
def _mail_mail_create(model, *args, **kwargs):
|
||||
res = mail_create_origin(model, *args, **kwargs)
|
||||
self._new_mails += res.sudo()
|
||||
@@ -80,11 +65,13 @@ class MockEmail(common.BaseCase):
|
||||
return mail_unlink_origin(model, *args, **kwargs)
|
||||
return True
|
||||
|
||||
with patch.object(IrMailServer, 'connect', autospec=True, wraps=IrMailServer, side_effect=_ir_mail_server_connect) as ir_mail_server_connect_mock, \
|
||||
patch.object(IrMailServer, 'build_email', autospec=True, wraps=IrMailServer, side_effect=_ir_mail_server_build_email) as ir_mail_server_build_email_mock, \
|
||||
patch.object(IrMailServer, 'send_email', autospec=True, wraps=IrMailServer, side_effect=_ir_mail_server_send_email) as ir_mail_server_send_email_mock, \
|
||||
patch.object(MailMail, 'create', autospec=True, wraps=MailMail, side_effect=_mail_mail_create) as _mail_mail_create_mock, \
|
||||
patch.object(MailMail, 'unlink', autospec=True, wraps=MailMail, side_effect=_mail_mail_unlink) as mail_mail_unlink_mock:
|
||||
with self.mock_smtplib_connection(), \
|
||||
patch.object(IrMailServer, 'build_email', autospec=True, wraps=IrMailServer, side_effect=_ir_mail_server_build_email) as build_email_mocked, \
|
||||
patch.object(IrMailServer, 'send_email', autospec=True, wraps=IrMailServer, side_effect=send_email_origin) as send_email_mocked, \
|
||||
patch.object(MailMail, 'create', autospec=True, wraps=MailMail, side_effect=_mail_mail_create), \
|
||||
patch.object(MailMail, 'unlink', autospec=True, wraps=MailMail, side_effect=_mail_mail_unlink):
|
||||
self.build_email_mocked = build_email_mocked
|
||||
self.send_email_mocked = send_email_mocked
|
||||
yield
|
||||
|
||||
def _init_mail_mock(self):
|
||||
@@ -92,10 +79,6 @@ class MockEmail(common.BaseCase):
|
||||
self._mails_args = []
|
||||
self._new_mails = self.env['mail.mail'].sudo()
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# GATEWAY TOOLS
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@classmethod
|
||||
def _init_mail_gateway(cls):
|
||||
cls.alias_domain = 'test.com'
|
||||
@@ -108,6 +91,26 @@ class MockEmail(common.BaseCase):
|
||||
cls.env['ir.config_parameter'].set_param('mail.default.from', cls.default_from)
|
||||
cls.mailer_daemon_email = formataddr(('MAILER-DAEMON', '%s@%s' % (cls.alias_bounce, cls.alias_domain)))
|
||||
|
||||
@classmethod
|
||||
def _init_outgoing_gateway(cls):
|
||||
cls.env['ir.mail_server'].search([]).unlink()
|
||||
cls.mail_server_domain, cls.mail_server_global = cls.env['ir.mail_server'].create([
|
||||
{'from_filter': 'test.com',
|
||||
'name': 'Domain Based Server',
|
||||
'smtp_encryption': 'none',
|
||||
'smtp_host': 'smtp_host',
|
||||
},
|
||||
{'from_filter': False,
|
||||
'name': 'No FromFilter Server',
|
||||
'smtp_encryption': 'none',
|
||||
'smtp_host': 'smtp_host',
|
||||
}
|
||||
])
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# GATEWAY TOOLS
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def format(self, template, to='groups@example.com, other@gmail.com', subject='Frogs',
|
||||
email_from='Sylvie Lelitre <test.sylvie.lelitre@agrolait.com>', return_path='', cc='',
|
||||
extra='', msg_id='<1198923581.41972151344608186760.JavaMail@agrolait.com>',
|
||||
@@ -316,7 +319,7 @@ class MockEmail(common.BaseCase):
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def assertMailMail(self, recipients, status,
|
||||
check_mail_mail=True, mail_message=None, author=None,
|
||||
mail_message=None, author=None,
|
||||
content=None, fields_values=None, email_values=None):
|
||||
""" Assert mail.mail records are created and maybe sent as emails. Allow
|
||||
asserting their content. Records to check are the one generated when
|
||||
@@ -335,8 +338,6 @@ class MockEmail(common.BaseCase):
|
||||
:param email_values: if given, should be a dictionary of keys / values
|
||||
allowing to check sent email additional values (if any).
|
||||
See ``assertSentEmail``;
|
||||
|
||||
:param check_mail_mail: deprecated, use ``assertSentEmail`` if False
|
||||
"""
|
||||
found_mail = self._find_mail_mail_wpartners(recipients, status, mail_message=mail_message, author=author)
|
||||
self.assertTrue(bool(found_mail))
|
||||
@@ -370,8 +371,6 @@ class MockEmail(common.BaseCase):
|
||||
:param email_values: if given, should be a dictionary of keys / values
|
||||
allowing to check sent email additional values (if any).
|
||||
See ``assertSentEmail``;
|
||||
|
||||
:param check_mail_mail: deprecated, use ``assertSentEmail`` if False
|
||||
"""
|
||||
for email_to in emails:
|
||||
found_mail = self._find_mail_mail_wemail(email_to, status, mail_message=mail_message, author=author)
|
||||
@@ -410,6 +409,16 @@ class MockEmail(common.BaseCase):
|
||||
found_mail[fname], fvalue,
|
||||
'Mail: expected %s for %s, got %s' % (fvalue, fname, found_mail[fname]))
|
||||
|
||||
def assertMessageFields(self, message, fields_values):
|
||||
""" Just a quick helper to check a mail.message content by giving directly
|
||||
a dict for fields. Allows to hide a lot of assertEqual under a simple
|
||||
call with a dictionary of expected values. """
|
||||
for fname, fvalue in fields_values.items():
|
||||
self.assertEqual(
|
||||
message[fname], fvalue,
|
||||
'Message: expected %s for %s, got %s' % (fvalue, fname, message[fname])
|
||||
)
|
||||
|
||||
def assertNoMail(self, recipients, mail_message=None, author=None):
|
||||
""" Check no mail.mail and email was generated during gateway mock. """
|
||||
try:
|
||||
@@ -435,8 +444,10 @@ class MockEmail(common.BaseCase):
|
||||
:param values: dictionary of additional values to check email content;
|
||||
"""
|
||||
base_expected = {}
|
||||
for fname in ['reply_to', 'subject', 'attachments', 'body', 'references',
|
||||
'body_content', 'body_alternative_content', 'references_content']:
|
||||
for fname in ['author_id', 'reply_to',
|
||||
'subject', 'body', 'body_content', 'body_alternative_content',
|
||||
'references', 'references_content',
|
||||
'attachments']:
|
||||
if fname in values:
|
||||
base_expected[fname] = values[fname]
|
||||
|
||||
@@ -461,9 +472,14 @@ class MockEmail(common.BaseCase):
|
||||
debug_info = '-'.join('From: %s-To: %s' % (mail['email_from'], mail['email_to']) for mail in self._mails) if not bool(sent_mail) else ''
|
||||
self.assertTrue(bool(sent_mail), 'Expected mail from %s to %s not found in %s' % (expected['email_from'], expected['email_to'], debug_info))
|
||||
|
||||
for val in ['reply_to', 'subject', 'references', 'attachments']:
|
||||
for val in ['reply_to', 'subject', 'references']:
|
||||
if val in expected:
|
||||
self.assertEqual(expected[val], sent_mail[val], 'Value for %s: expected %s, received %s' % (val, expected[val], sent_mail[val]))
|
||||
if 'attachments' in expected:
|
||||
self.assertEqual(
|
||||
sorted(expected['attachments']), sorted(sent_mail['attachments']),
|
||||
'Value for %s: expected %s, received %s' % ('attachments', expected['attachments'], sent_mail['attachments'])
|
||||
)
|
||||
if 'attachments_info' in values:
|
||||
attachments = sent_mail['attachments']
|
||||
for attachment_info in values['attachments_info']:
|
||||
@@ -473,12 +489,18 @@ class MockEmail(common.BaseCase):
|
||||
if attachment_info.get('type'):
|
||||
self.assertEqual(attachment[2], attachment_info['type'])
|
||||
self.assertEqual(len(values['attachments_info']), len(attachments))
|
||||
for val in ['body']:
|
||||
for val in ['body', 'body_alternative']:
|
||||
if val in expected:
|
||||
self.assertHtmlEqual(expected[val], sent_mail[val], 'Value for %s: expected %s, received %s' % (val, expected[val], sent_mail[val]))
|
||||
for val in ['body_content', 'body_alternative', 'references_content']:
|
||||
self.assertHtmlEqual(
|
||||
expected[val], sent_mail[val],
|
||||
'Value for %s: expected %s, received %s' % (val, expected[val], sent_mail[val])
|
||||
)
|
||||
for val in ['body_content', 'body_alternative_content', 'references_content']:
|
||||
if val in expected:
|
||||
self.assertIn(expected[val], sent_mail[val[:-8]], 'Value for %s: %s does not contain %s' % (val, sent_mail[val[:-8]], expected[val]))
|
||||
self.assertIn(
|
||||
expected[val], sent_mail[val[:-8]],
|
||||
'Value for %s: %s does not contain %s' % (val, sent_mail[val[:-8]], expected[val])
|
||||
)
|
||||
|
||||
|
||||
class MailCase(MockEmail):
|
||||
@@ -496,10 +518,11 @@ class MailCase(MockEmail):
|
||||
("UNKNOWN", "Unknown error")
|
||||
"""
|
||||
_test_context = {
|
||||
'mail_channel_nosubscribe': True,
|
||||
'mail_create_nolog': True,
|
||||
'mail_create_nosubscribe': True,
|
||||
'mail_notrack': True,
|
||||
'no_reset_password': True
|
||||
'no_reset_password': True,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
@@ -507,7 +530,7 @@ class MailCase(MockEmail):
|
||||
return record.with_context(
|
||||
mail_create_nolog=False,
|
||||
mail_create_nosubscribe=False,
|
||||
mail_notrack=False
|
||||
mail_notrack=False,
|
||||
)
|
||||
|
||||
def flush_tracking(self):
|
||||
@@ -627,19 +650,19 @@ class MailCase(MockEmail):
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@contextmanager
|
||||
def assertSinglePostNotifications(self, recipients_info, message_info=None, mail_unlink_sent=False, sim_error=None):
|
||||
def assertSinglePostNotifications(self, recipients_info, message_info=None, mail_unlink_sent=False):
|
||||
""" Shortcut to assertMsgNotifications when having a single message to check. """
|
||||
r_info = dict(message_info if message_info else {})
|
||||
r_info.setdefault('content', '')
|
||||
r_info['notif'] = recipients_info
|
||||
with self.assertPostNotifications([r_info], mail_unlink_sent=mail_unlink_sent, sim_error=sim_error):
|
||||
with self.assertPostNotifications([r_info], mail_unlink_sent=mail_unlink_sent):
|
||||
yield
|
||||
|
||||
@contextmanager
|
||||
def assertPostNotifications(self, recipients_info, mail_unlink_sent=False, sim_error=None):
|
||||
def assertPostNotifications(self, recipients_info, mail_unlink_sent=False):
|
||||
""" Check content of notifications. """
|
||||
try:
|
||||
with self.mock_mail_gateway(mail_unlink_sent=mail_unlink_sent, sim_error=sim_error), self.mock_bus(), self.mock_mail_app():
|
||||
with self.mock_mail_gateway(mail_unlink_sent=mail_unlink_sent), self.mock_bus(), self.mock_mail_app():
|
||||
yield
|
||||
finally:
|
||||
done_msgs, done_notifs = self.assertMailNotifications(self._new_msgs, recipients_info)
|
||||
@@ -659,7 +682,7 @@ class MailCase(MockEmail):
|
||||
@contextmanager
|
||||
def assertNoNotifications(self):
|
||||
try:
|
||||
with self.mock_mail_gateway(mail_unlink_sent=False, sim_error=None), self.mock_bus(), self.mock_mail_app():
|
||||
with self.mock_mail_gateway(mail_unlink_sent=False), self.mock_bus(), self.mock_mail_app():
|
||||
yield
|
||||
finally:
|
||||
self.assertFalse(bool(self._new_msgs))
|
||||
@@ -891,9 +914,14 @@ class MailCommon(common.TransactionCase, MailCase):
|
||||
super(MailCommon, cls).setUpClass()
|
||||
# give default values for all email aliases and domain
|
||||
cls._init_mail_gateway()
|
||||
cls._init_outgoing_gateway()
|
||||
# ensure admin configuration
|
||||
cls.user_admin = cls.env.ref('base.user_admin')
|
||||
cls.user_admin.write({'notification_type': 'inbox'})
|
||||
cls.user_admin.write({
|
||||
'country_id': cls.env.ref('base.be').id,
|
||||
'email': 'test.admin@test.example.com',
|
||||
'notification_type': 'inbox',
|
||||
})
|
||||
cls.partner_admin = cls.env.ref('base.partner_admin')
|
||||
cls.company_admin = cls.user_admin.company_id
|
||||
cls.company_admin.write({'email': 'company@example.com'})
|
||||
@@ -905,9 +933,11 @@ class MailCommon(common.TransactionCase, MailCase):
|
||||
|
||||
# test standard employee
|
||||
cls.user_employee = mail_new_test_user(
|
||||
cls.env, login='employee',
|
||||
groups='base.group_user,mail.group_mail_template_editor',
|
||||
cls.env,
|
||||
company_id=cls.company_admin.id,
|
||||
country_id=cls.env.ref('base.be').id,
|
||||
groups='base.group_user,mail.group_mail_template_editor',
|
||||
login='employee',
|
||||
name='Ernest Employee',
|
||||
notification_type='inbox',
|
||||
signature='--\nErnest'
|
||||
@@ -939,12 +969,26 @@ class MailCommon(common.TransactionCase, MailCase):
|
||||
groups='base.group_user',
|
||||
company_id=cls.company_2.id,
|
||||
company_ids=[(4, cls.company_2.id)],
|
||||
email='enguerrand@example.com',
|
||||
name='Enguerrand Employee C2',
|
||||
notification_type='inbox',
|
||||
signature='--\nEnguerrand'
|
||||
)
|
||||
cls.partner_employee_c2 = cls.user_employee_c2.partner_id
|
||||
|
||||
# test erp manager employee
|
||||
cls.user_erp_manager = mail_new_test_user(
|
||||
cls.env,
|
||||
company_id=cls.company_2.id,
|
||||
company_ids=[(6, 0, (cls.company_admin + cls.company_2).ids)],
|
||||
email='etchenne@example.com',
|
||||
groups='base.group_user,base.group_erp_manager,mail.group_mail_template_editor',
|
||||
login='erp_manager',
|
||||
name='Etchenne Tchagada',
|
||||
notification_type='inbox',
|
||||
signature='--\nEtchenne',
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _activate_multi_lang(cls, lang_code='es_ES', layout_arch_db=None, test_record=False, test_template=False):
|
||||
""" Summary of es_ES matching done here (a bit hardcoded to ease tests)
|
||||
@@ -1097,15 +1141,18 @@ class MailCommon(common.TransactionCase, MailCase):
|
||||
})
|
||||
cls.env['ir.translation'].create(translations_tocreate)
|
||||
|
||||
def _generate_attachments_data(self, count, res_model=None, res_id=None):
|
||||
def _generate_attachments_data(self, count, res_model=None, res_id=None, attach_values=None):
|
||||
# attachment visibility depends on what they are attached to
|
||||
attach_values = attach_values or {}
|
||||
if res_model is None:
|
||||
res_model = self.template._name
|
||||
if res_id is None:
|
||||
res_id = self.template.id
|
||||
return [{
|
||||
'name': '%02d.txt' % x,
|
||||
'datas': base64.b64encode(b'Att%02d' % x),
|
||||
'datas': base64.b64encode(b'AttContent_%02d' % x),
|
||||
'name': 'AttFileName_%02d.txt' % x,
|
||||
'mimetype': 'text/plain',
|
||||
'res_model': res_model,
|
||||
'res_id': res_id,
|
||||
**attach_values,
|
||||
} for x in range(count)]
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from functools import partial
|
||||
|
||||
from odoo.addons.mail.tests.common import mail_new_test_user
|
||||
from odoo.addons.mail.tests.common import MailCommon
|
||||
from odoo.exceptions import AccessError, UserError
|
||||
|
||||
mail_channel_new_test_user = partial(mail_new_test_user, context={'mail_channel_nosubscribe': False})
|
||||
|
||||
|
||||
class TestMailChannelMembers(MailCommon):
|
||||
|
||||
@@ -22,23 +26,23 @@ class TestMailChannelMembers(MailCommon):
|
||||
'res_id': cls.secret_group.id,
|
||||
})
|
||||
|
||||
cls.user_1 = mail_new_test_user(
|
||||
cls.user_1 = mail_channel_new_test_user(
|
||||
cls.env, login='user_1',
|
||||
name='User 1',
|
||||
groups='base.group_user,mail.secret_group')
|
||||
cls.user_2 = mail_new_test_user(
|
||||
cls.user_2 = mail_channel_new_test_user(
|
||||
cls.env, login='user_2',
|
||||
name='User 2',
|
||||
groups='base.group_user,mail.secret_group')
|
||||
cls.user_3 = mail_new_test_user(
|
||||
cls.user_3 = mail_channel_new_test_user(
|
||||
cls.env, login='user_3',
|
||||
name='User 3',
|
||||
groups='base.group_user,mail.secret_group')
|
||||
cls.user_portal = mail_new_test_user(
|
||||
cls.user_portal = mail_channel_new_test_user(
|
||||
cls.env, login='user_portal',
|
||||
name='User Portal',
|
||||
groups='base.group_portal')
|
||||
cls.user_public = mail_new_test_user(
|
||||
cls.user_public = mail_channel_new_test_user(
|
||||
cls.env, login='user_ublic',
|
||||
name='User Public',
|
||||
groups='base.group_public')
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests import users
|
||||
from odoo.addons.mail.tests.common import MailCommon
|
||||
from odoo.tests import tagged, users
|
||||
|
||||
|
||||
@tagged('mail_composer')
|
||||
class TestMailComposer(MailCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMailComposer, cls).setUpClass()
|
||||
@@ -47,9 +49,11 @@ class TestMailComposer(MailCommon):
|
||||
|
||||
values = mail_compose_message.get_mail_values(self.partner_employee.ids)
|
||||
|
||||
self.assertIn(self.body_html,
|
||||
self.assertIn(
|
||||
self.body_html,
|
||||
values[self.partner_employee.id]['body_html'],
|
||||
'We must preserve (mso) comments in email html')
|
||||
'We must preserve (mso) comments in email html'
|
||||
)
|
||||
|
||||
@users('employee')
|
||||
def test_mail_mass_mode_compose_with_mso(self):
|
||||
@@ -69,6 +73,8 @@ class TestMailComposer(MailCommon):
|
||||
|
||||
values = composer.get_mail_values(self.partner_employee.ids)
|
||||
|
||||
self.assertIn(self.body_html,
|
||||
self.assertIn(
|
||||
self.body_html,
|
||||
values[self.partner_employee.id]['body_html'],
|
||||
'We must preserve (mso) comments in email html')
|
||||
'We must preserve (mso) comments in email html'
|
||||
)
|
||||
|
||||
@@ -545,7 +545,7 @@ class MailComposer(models.TransientModel):
|
||||
elif template_id:
|
||||
values = self.generate_email_for_composer(
|
||||
template_id, [res_id],
|
||||
['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids', 'mail_server_id']
|
||||
['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids', 'mail_server_id']
|
||||
)[res_id]
|
||||
# transform attachments into attachment_ids; not attached to the document because this will
|
||||
# be done further in the posting process, allowing to clean database if email not send
|
||||
|
||||
@@ -60,8 +60,10 @@ class MailTestActivity(models.Model):
|
||||
summary=action_summary
|
||||
)
|
||||
|
||||
def action_close(self, action_feedback):
|
||||
self.activity_feedback(['test_mail.mail_act_test_todo'], feedback=action_feedback)
|
||||
def action_close(self, action_feedback, attachment_ids=None):
|
||||
self.activity_feedback(['test_mail.mail_act_test_todo'],
|
||||
feedback=action_feedback,
|
||||
attachment_ids=attachment_ids)
|
||||
|
||||
|
||||
class MailTestTicket(models.Model):
|
||||
@@ -111,6 +113,18 @@ class MailTestTicket(models.Model):
|
||||
return super(MailTestTicket, self)._track_subtype(init_values)
|
||||
|
||||
|
||||
class MailTestTicketMC(models.Model):
|
||||
""" Just mail.test.ticket, but multi company. Kept as different model to
|
||||
avoid messing with existing tests, notably performance, and ease backward
|
||||
comparison. """
|
||||
_description = 'Ticket-like model'
|
||||
_name = 'mail.test.ticket.mc'
|
||||
_inherit = ['mail.test.ticket']
|
||||
|
||||
company_id = fields.Many2one('res.company', 'Company', default=lambda self: self.env.company)
|
||||
container_id = fields.Many2one('mail.test.container.mc', tracking=True)
|
||||
|
||||
|
||||
class MailTestContainer(models.Model):
|
||||
""" This model can be used in tests when container records like projects
|
||||
or teams are required. """
|
||||
@@ -144,6 +158,18 @@ class MailTestContainer(models.Model):
|
||||
values['alias_parent_thread_id'] = self.id
|
||||
return values
|
||||
|
||||
class MailTestContainerMC(models.Model):
|
||||
""" Just mail.test.container, but multi company. Kept as different model to
|
||||
avoid messing with existing tests, notably performance, and ease backward
|
||||
comparison. """
|
||||
_description = 'Project-like model with alias (MC)'
|
||||
_name = 'mail.test.container.mc'
|
||||
_mail_post_access = 'read'
|
||||
_inherit = ['mail.test.container']
|
||||
|
||||
company_id = fields.Many2one('res.company', 'Company', default=lambda self: self.env.company)
|
||||
|
||||
|
||||
class MailTestComposerMixin(models.Model):
|
||||
""" A simple invite-like wizard using the composer mixin, rendering on
|
||||
itself. """
|
||||
|
||||
@@ -11,12 +11,16 @@ access_mail_test_activity_portal,mail.test.activity.portal,model_mail_test_activ
|
||||
access_mail_test_activity_user,mail.test.activity.user,model_mail_test_activity,base.group_user,1,1,1,1
|
||||
access_mail_test_field_type_portal,mail.test.field.type.portal,model_mail_test_field_type,base.group_portal,0,0,0,0
|
||||
access_mail_test_field_type_user,mail.test.field.type.user,model_mail_test_field_type,base.group_user,1,1,1,1
|
||||
access_mail_test_ticket_portal,mail.test.ticket.portal,model_mail_test_ticket,base.group_portal,0,0,0,0
|
||||
access_mail_test_ticket_portal,mail.test.ticket.portal,model_mail_test_ticket,base.group_portal,1,0,0,0
|
||||
access_mail_test_ticket_user,mail.test.ticket.user,model_mail_test_ticket,base.group_user,1,1,1,1
|
||||
access_mail_test_ticket_mc_portal,mail.test.ticket.mc.portal,model_mail_test_ticket_mc,base.group_portal,1,0,0,0
|
||||
access_mail_test_ticket_mc_user,mail.test.ticket.mc.user,model_mail_test_ticket_mc,base.group_user,1,1,1,1
|
||||
access_mail_test_composer_mixin_all,mail.test.composer.mixin.all,model_mail_test_composer_mixin,,0,0,0,0
|
||||
access_mail_test_composer_mixin_user,mail.test.composer.mixin.user,model_mail_test_composer_mixin,base.group_user,1,1,1,1
|
||||
access_mail_test_container_portal,mail.test.container_portal,model_mail_test_container,base.group_portal,1,1,0,0
|
||||
access_mail_test_container_portal,mail.test.container_portal,model_mail_test_container,base.group_portal,1,0,0,0
|
||||
access_mail_test_container_user,mail.test.container.user,model_mail_test_container,base.group_user,1,1,1,1
|
||||
access_mail_test_container_mc_portal,mail.test.container.mc.portal,model_mail_test_container_mc,base.group_portal,1,0,0,0
|
||||
access_mail_test_container_mc_user,mail.test.container.mc.user,model_mail_test_container_mc,base.group_user,1,1,1,1
|
||||
access_mail_test_cc_portal,mail.test.cc.portal,model_mail_test_cc,base.group_portal,1,0,0,0
|
||||
access_mail_test_cc_user,mail.test.cc.user,model_mail_test_cc,base.group_user,1,1,1,1
|
||||
access_mail_test_lang_portal,mail.test.lang.portal,model_mail_test_lang,base.group_portal,1,0,0,0
|
||||
|
||||
|
@@ -1,11 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
|
||||
<record id="mail_test_multi_company_rule" model="ir.rule">
|
||||
<field name="name">Mail Test Multi Company</field>
|
||||
<field name="model_id" ref="test_mail.model_mail_test_multi_company"/>
|
||||
<field eval="True" name="global"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
<record id="mail_test_multi_company_rule" model="ir.rule">
|
||||
<field name="name">Mail Test Multi Company</field>
|
||||
<field name="model_id" ref="test_mail.model_mail_test_multi_company"/>
|
||||
<field eval="True" name="global"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<!-- TICKET-LIKE -->
|
||||
<record id="mail_test_ticket_rule_portal" model="ir.rule">
|
||||
<field name="name">Portal Mail Test Ticket</field>
|
||||
<field name="model_id" ref="test_mail.model_mail_test_ticket"/>
|
||||
<field name="domain_force">[('message_partner_ids', 'in', [user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<!-- MULTI COMPANY TICKET LIKE -->
|
||||
<record id="mail_test_ticket_mc_rule" model="ir.rule">
|
||||
<field name="name">Mail Test Ticket Multi Company</field>
|
||||
<field name="model_id" ref="test_mail.model_mail_test_ticket_mc"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
<record id="mail_test_ticket_mc_rule_portal" model="ir.rule">
|
||||
<field name="name">Portal Mail Test Ticket Multi Company</field>
|
||||
<field name="model_id" ref="test_mail.model_mail_test_ticket_mc"/>
|
||||
<field name="domain_force">[('message_partner_ids', 'in', [user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<!-- PROJECT-LIKE -->
|
||||
<record id="mail_test_container_rule_portal" model="ir.rule">
|
||||
<field name="name">Portal Mail Test Container</field>
|
||||
<field name="model_id" ref="test_mail.model_mail_test_container"/>
|
||||
<field name="domain_force">[('message_partner_ids', 'in', [user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<!-- MULTI COMPANY PROJECT LIKE -->
|
||||
<record id="mail_test_container_mc_rule" model="ir.rule">
|
||||
<field name="name">Mail Test Container Multi Company</field>
|
||||
<field name="model_id" ref="test_mail.model_mail_test_container_mc"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
<field name="global" eval="True"/>
|
||||
</record>
|
||||
<record id="mail_test_container_mc_rule_portal" model="ir.rule">
|
||||
<field name="name">Portal Mail Test Container Multi Company</field>
|
||||
<field name="model_id" ref="test_mail.model_mail_test_container_mc"/>
|
||||
<field name="domain_force">[('message_partner_ids', 'in', [user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -9,27 +9,29 @@ class TestMailCommon(MailCommon):
|
||||
""" Main entry point for functional tests. """
|
||||
|
||||
@classmethod
|
||||
def _create_channel_listener(cls):
|
||||
cls.channel_listen = cls.env['mail.channel'].with_context(cls._test_context).create({'name': 'Listener'})
|
||||
|
||||
@classmethod
|
||||
def _create_records_for_batch(cls, model, count):
|
||||
# TDE note: to be cleaned in master
|
||||
def _create_records_for_batch(cls, model, count, additional_values=None):
|
||||
additional_values = additional_values or {}
|
||||
records = cls.env[model]
|
||||
partners = cls.env['res.partner']
|
||||
country_id = cls.env.ref('base.be').id
|
||||
|
||||
partners = cls.env['res.partner'].with_context(**cls._test_context).create([{
|
||||
'name': 'Partner_%s' % (x),
|
||||
'email': '_test_partner_%s@example.com' % (x),
|
||||
'country_id': country_id,
|
||||
'mobile': '047500%02d%02d' % (x, x)
|
||||
} for x in range(count)])
|
||||
base_values = [
|
||||
{'name': 'Test_%s' % idx,
|
||||
**additional_values,
|
||||
} for idx in range(count)
|
||||
]
|
||||
|
||||
records = cls.env[model].with_context(**cls._test_context).create([{
|
||||
'name': 'Test_%s' % (x),
|
||||
'customer_id': partners[x].id,
|
||||
} for x in range(count)])
|
||||
if 'customer_id' in cls.env[model]:
|
||||
partners = cls.env['res.partner'].with_context(**cls._test_context).create([{
|
||||
'name': 'Partner_%s' % idx,
|
||||
'email': '_test_partner_%s@example.com' % idx,
|
||||
'country_id': country_id,
|
||||
'mobile': '047500%02d%02d' % (idx, idx)
|
||||
} for idx in range(count)])
|
||||
for values, partner in zip(base_values, partners):
|
||||
values['customer_id'] = partner.id
|
||||
|
||||
records = cls.env[model].with_context(**cls._test_context).create(base_values)
|
||||
|
||||
cls.records = cls._reset_mail_context(records)
|
||||
cls.partners = partners
|
||||
|
||||
@@ -11,6 +11,7 @@ from odoo.tests import tagged
|
||||
from odoo.tests.common import users, Form
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
@tagged('mail_composer')
|
||||
class TestMailComposer(TestMailCommon, TestRecipients):
|
||||
""" Test Composer internals """
|
||||
@@ -18,7 +19,6 @@ class TestMailComposer(TestMailCommon, TestRecipients):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMailComposer, cls).setUpClass()
|
||||
cls._init_mail_gateway()
|
||||
|
||||
# ensure employee can create partners, necessary for templates
|
||||
cls.user_employee.write({
|
||||
@@ -47,7 +47,10 @@ class TestMailComposer(TestMailCommon, TestRecipients):
|
||||
'customer_id': cls.partner_1.id,
|
||||
'user_id': cls.user_employee_2.id,
|
||||
})
|
||||
cls.test_records, cls.test_partners = cls._create_records_for_batch('mail.test.ticket', 2)
|
||||
cls.test_records, cls.test_partners = cls._create_records_for_batch(
|
||||
'mail.test.ticket', 2,
|
||||
additional_values={'user_id': cls.user_employee_2.id}
|
||||
)
|
||||
|
||||
cls.test_report = cls.env['ir.actions.report'].create({
|
||||
'name': 'Test Report on mail test ticket',
|
||||
@@ -59,24 +62,17 @@ class TestMailComposer(TestMailCommon, TestRecipients):
|
||||
|
||||
cls.test_from = '"John Doe" <john@example.com>'
|
||||
|
||||
cls.mail_server = cls.env['ir.mail_server'].create({
|
||||
'name': 'Dummy Test Server',
|
||||
'smtp_host': 'smtp.pizza.moc',
|
||||
'smtp_port': 17,
|
||||
'smtp_encryption': 'ssl',
|
||||
'sequence': 666,
|
||||
})
|
||||
|
||||
cls.template = cls.env['mail.template'].create({
|
||||
'auto_delete': True,
|
||||
'name': 'TestTemplate',
|
||||
'subject': 'TemplateSubject {{ object.name }}',
|
||||
'body_html': '<p>TemplateBody <t t-esc="object.name"></t></p>',
|
||||
'partner_to': '{{ object.customer_id.id if object.customer_id else "" }}',
|
||||
'email_to': '{{ (object.email_from if not object.customer_id else "") }}',
|
||||
'email_from': '{{ (object.user_id.email_formatted or user.email_formatted) }}',
|
||||
'mail_server_id': cls.mail_server_domain.id,
|
||||
'model_id': cls.env['ir.model']._get('mail.test.ticket').id,
|
||||
'mail_server_id': cls.mail_server.id,
|
||||
'auto_delete': True,
|
||||
'reply_to': '{{ ctx.get("custom_reply_to") or "info@test.example.com" }}',
|
||||
})
|
||||
|
||||
def _get_web_context(self, records, add_web=True, **values):
|
||||
@@ -108,15 +104,28 @@ class TestComposerForm(TestMailComposer):
|
||||
|
||||
@users('employee')
|
||||
def test_mail_composer_comment(self):
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(self._get_web_context(self.test_record, add_web=True)))
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(
|
||||
self._get_web_context(self.test_record, add_web=True)
|
||||
))
|
||||
# auto_delete not displayed currently in view
|
||||
# self.assertFalse(composer_form.auto_delete)
|
||||
# self.assertFalse(composer_form.auto_delete_message)
|
||||
# author_id not displayed currently in view
|
||||
# self.assertEqual(composer_form.author_id, self.env.user.partner_id)
|
||||
self.assertFalse(composer_form.body)
|
||||
self.assertEqual(composer_form.composition_mode, 'comment')
|
||||
self.assertEqual(composer_form.email_from, self.env.user.email_formatted)
|
||||
self.assertFalse(composer_form.mail_server_id)
|
||||
self.assertEqual(composer_form.model, self.test_record._name)
|
||||
self.assertFalse(composer_form.partner_ids)
|
||||
# record name not displayed currently in view
|
||||
# self.assertEqual(composer_form.record_name, self.test_record.name, 'MailComposer: comment mode should compute record name')
|
||||
self.assertFalse(composer_form.reply_to)
|
||||
self.assertFalse(composer_form.reply_to_force_new)
|
||||
self.assertEqual(composer_form.res_id, self.test_record.id)
|
||||
self.assertEqual(
|
||||
composer_form.subject, 'Re: %s' % self.test_record.name,
|
||||
'MailComposer: comment mode should have default subject Re: record_name')
|
||||
# record name not displayed currently in view
|
||||
# self.assertEqual(composer_form.record_name, self.test_record.name, 'MailComposer: comment mode should compute record name')
|
||||
self.assertFalse(composer_form.reply_to_force_new)
|
||||
self.assertEqual(composer_form.composition_mode, 'comment')
|
||||
self.assertEqual(composer_form.model, self.test_record._name)
|
||||
|
||||
@users('employee')
|
||||
def test_mail_composer_comment_attachments(self):
|
||||
@@ -156,7 +165,7 @@ class TestComposerForm(TestMailComposer):
|
||||
report_attachments = [att for att in composer_form.attachment_ids if att not in template_1_attachments]
|
||||
self.assertEqual(len(report_attachments), 1)
|
||||
tpl_attachments = composer_form.attachment_ids[:] - report_attachments[0]
|
||||
self.assertEqual(tpl_attachments, self.env['ir.attachment'])
|
||||
self.assertFalse(tpl_attachments)
|
||||
|
||||
# change back to template 1
|
||||
composer_form.template_id = template_1
|
||||
@@ -170,29 +179,77 @@ class TestComposerForm(TestMailComposer):
|
||||
composer_form.template_id = self.env['mail.template']
|
||||
self.assertEqual(len(composer_form.attachment_ids), 0)
|
||||
|
||||
@users('employee')
|
||||
def test_mail_composer_comment_wtpl(self):
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(
|
||||
self._get_web_context(self.test_record, add_web=True, default_template_id=self.template.id)
|
||||
))
|
||||
# auto_delete not displayed currently in view
|
||||
# self.assertTrue(composer_form.auto_delete)
|
||||
# self.assertFalse(composer_form.auto_delete_message)
|
||||
# author_id not displayed currently in view
|
||||
# self.assertEqual(composer_form.author_id, self.env.user.partner_id)
|
||||
self.assertEqual(composer_form.body, '<p>TemplateBody %s</p>' % self.test_record.name)
|
||||
self.assertEqual(composer_form.composition_mode, 'comment')
|
||||
self.assertEqual(composer_form.email_from, self.user_employee_2.email_formatted)
|
||||
self.assertEqual(composer_form.mail_server_id, self.mail_server_domain)
|
||||
self.assertEqual(composer_form.model, self.test_record._name)
|
||||
self.assertEqual(composer_form.partner_ids[:], self.partner_1)
|
||||
# record name not displayed currently in view
|
||||
# self.assertEqual(composer_form.record_name, self.test_record.name, 'MailComposer: comment mode should compute record name')
|
||||
self.assertEqual(composer_form.reply_to, 'info@test.example.com')
|
||||
self.assertFalse(composer_form.reply_to_force_new)
|
||||
self.assertEqual(composer_form.res_id, self.test_record.id)
|
||||
self.assertEqual(composer_form.subject, 'TemplateSubject %s' % self.test_record.name)
|
||||
|
||||
@users('employee')
|
||||
def test_mail_composer_mass(self):
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(self._get_web_context(self.test_records, add_web=True)))
|
||||
self.assertFalse(composer_form.subject, 'MailComposer: mass mode should have void default subject if no template')
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(
|
||||
self._get_web_context(self.test_records, add_web=True)
|
||||
))
|
||||
# auto_delete not displayed currently in view
|
||||
# self.assertFalse(composer_form.auto_delete)
|
||||
# self.assertFalse(composer_form.auto_delete_message)
|
||||
# author_id not displayed currently in view
|
||||
# self.assertEqual(composer_form.author_id, self.env.user.partner_id)
|
||||
self.assertFalse(composer_form.body)
|
||||
self.assertEqual(composer_form.composition_mode, 'mass_mail')
|
||||
self.assertEqual(composer_form.email_from, self.env.user.email_formatted)
|
||||
self.assertFalse(composer_form.mail_server_id)
|
||||
self.assertEqual(composer_form.model, self.test_records._name)
|
||||
# record name not displayed currently in view
|
||||
# self.assertFalse(composer_form.record_name, 'MailComposer: mass mode should have void record name')
|
||||
self.assertFalse(composer_form.reply_to)
|
||||
self.assertFalse(composer_form.reply_to_force_new)
|
||||
self.assertEqual(composer_form.composition_mode, 'mass_mail')
|
||||
self.assertEqual(composer_form.model, self.test_records._name)
|
||||
self.assertEqual(composer_form.res_id, self.test_records[0].id,
|
||||
'MailComposer: even in mass mode web active_id presence may add a res_id')
|
||||
self.assertFalse(composer_form.subject, 'MailComposer: mass mode should have void default subject if no template')
|
||||
|
||||
@users('employee')
|
||||
def test_mail_composer_mass_wtpl(self):
|
||||
ctx = self._get_web_context(self.test_records, add_web=True, default_template_id=self.template.id)
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(ctx))
|
||||
self.assertEqual(composer_form.subject, self.template.subject,
|
||||
'MailComposer: mass mode should have template raw subject if template')
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(
|
||||
self._get_web_context(self.test_records, add_web=True, default_template_id=self.template.id)
|
||||
))
|
||||
# auto_delete not displayed currently in view
|
||||
# self.assertTrue(composer_form.auto_delete)
|
||||
# self.assertFalse(composer_form.auto_delete_message)
|
||||
# author_id not displayed currently in view
|
||||
# self.assertEqual(composer_form.author_id, self.env.user.partner_id)
|
||||
self.assertEqual(composer_form.body, self.template.body_html,
|
||||
'MailComposer: mass mode should have template raw body if template')
|
||||
self.assertEqual(composer_form.composition_mode, 'mass_mail')
|
||||
self.assertEqual(composer_form.email_from, self.template.email_from,
|
||||
'MailComposer: mass mode should have template raw email_from if template')
|
||||
self.assertEqual(composer_form.mail_server_id, self.mail_server_domain)
|
||||
self.assertEqual(composer_form.model, self.test_records._name)
|
||||
# record name not displayed currently in view
|
||||
# self.assertFalse(composer_form.record_name, 'MailComposer: mass mode should have void record name')
|
||||
self.assertEqual(composer_form.reply_to, self.template.reply_to)
|
||||
self.assertFalse(composer_form.reply_to_force_new)
|
||||
self.assertEqual(composer_form.composition_mode, 'mass_mail')
|
||||
self.assertEqual(composer_form.model, self.test_records._name)
|
||||
self.assertEqual(composer_form.res_id, self.test_records[0].id,
|
||||
'MailComposer: even in mass mode web active_id presence may add a res_id')
|
||||
self.assertEqual(composer_form.subject, self.template.subject,
|
||||
'MailComposer: mass mode should have template raw subject if template')
|
||||
|
||||
|
||||
@tagged('mail_composer')
|
||||
@@ -294,6 +351,10 @@ class TestComposerInternals(TestMailComposer):
|
||||
self.assertEqual(composer.subject, 'My amazing subject')
|
||||
self.assertEqual(composer.body, '<p>Test Body</p>')
|
||||
self.assertEqual(composer.mail_server_id.id, False)
|
||||
if composition_mode == 'comment':
|
||||
self.assertEqual(composer.record_name, self.test_record.name)
|
||||
else:
|
||||
self.assertFalse(composer.record_name)
|
||||
|
||||
# changing template should update its content
|
||||
composer.write({'template_id': self.template.id})
|
||||
@@ -305,10 +366,12 @@ class TestComposerInternals(TestMailComposer):
|
||||
self.assertEqual(composer.subject, 'TemplateSubject %s' % self.test_record.name)
|
||||
self.assertEqual(composer.body, '<p>TemplateBody %s</p>' % self.test_record.name)
|
||||
self.assertEqual(composer.mail_server_id, self.template.mail_server_id)
|
||||
self.assertEqual(composer.record_name, self.test_record.name)
|
||||
else:
|
||||
self.assertEqual(composer.subject, self.template.subject)
|
||||
self.assertEqual(composer.body, self.template.body_html)
|
||||
self.assertEqual(composer.mail_server_id, self.template.mail_server_id)
|
||||
self.assertFalse(composer.record_name)
|
||||
|
||||
# manual values is kept over template
|
||||
composer.write({'subject': 'Back to my amazing subject'})
|
||||
@@ -322,17 +385,19 @@ class TestComposerInternals(TestMailComposer):
|
||||
# values are reset
|
||||
if composition_mode == 'comment':
|
||||
self.assertEqual(composer.subject, 'Re: %s' % self.test_record.name)
|
||||
self.assertEqual(composer.body, '')
|
||||
self.assertFalse(composer.body)
|
||||
# TDE FIXME: server id is kept, not sure why
|
||||
# self.assertFalse(composer.mail_server_id.id)
|
||||
self.assertEqual(composer.mail_server_id, self.template.mail_server_id)
|
||||
self.assertEqual(composer.record_name, self.test_record.name)
|
||||
else:
|
||||
# values are reset TDE FIXME: strange for subject
|
||||
self.assertEqual(composer.subject, 'Back to my amazing subject')
|
||||
self.assertEqual(composer.body, '')
|
||||
self.assertFalse(composer.body)
|
||||
# TDE FIXME: server id is kept, not sure why
|
||||
# self.assertFalse(composer.mail_server_id.id)
|
||||
self.assertEqual(composer.mail_server_id, self.template.mail_server_id)
|
||||
self.assertFalse(composer.record_name)
|
||||
|
||||
# 2. check with default
|
||||
ctx['default_template_id'] = self.template.id
|
||||
@@ -347,10 +412,12 @@ class TestComposerInternals(TestMailComposer):
|
||||
self.assertEqual(composer.subject, 'TemplateSubject %s' % self.test_record.name)
|
||||
self.assertEqual(composer.body, '<p>TemplateBody %s</p>' % self.test_record.name)
|
||||
self.assertEqual(composer.mail_server_id, self.template.mail_server_id)
|
||||
self.assertEqual(composer.record_name, self.test_record.name)
|
||||
else:
|
||||
self.assertEqual(composer.subject, self.template.subject)
|
||||
self.assertEqual(composer.body, self.template.body_html)
|
||||
self.assertEqual(composer.mail_server_id, self.template.mail_server_id)
|
||||
self.assertFalse(composer.record_name)
|
||||
|
||||
# 3. check at create
|
||||
ctx.pop('default_template_id')
|
||||
@@ -365,10 +432,12 @@ class TestComposerInternals(TestMailComposer):
|
||||
self.assertEqual(composer.subject, 'TemplateSubject %s' % self.test_record.name)
|
||||
self.assertEqual(composer.body, '<p>TemplateBody %s</p>' % self.test_record.name)
|
||||
self.assertEqual(composer.mail_server_id, self.template.mail_server_id)
|
||||
self.assertEqual(composer.record_name, self.test_record.name)
|
||||
else:
|
||||
self.assertEqual(composer.subject, self.template.subject)
|
||||
self.assertEqual(composer.body, self.template.body_html)
|
||||
self.assertEqual(composer.mail_server_id, self.template.mail_server_id)
|
||||
self.assertFalse(composer.record_name)
|
||||
|
||||
# 4. template + user input
|
||||
ctx['default_template_id'] = self.template.id
|
||||
@@ -376,15 +445,155 @@ class TestComposerInternals(TestMailComposer):
|
||||
'subject': 'My amazing subject',
|
||||
'body': '<p>Test Body</p>',
|
||||
'mail_server_id': False,
|
||||
'record_name': 'CustomName',
|
||||
})
|
||||
|
||||
# creation values are taken
|
||||
self.assertEqual(composer.subject, 'My amazing subject')
|
||||
self.assertEqual(composer.body, '<p>Test Body</p>')
|
||||
self.assertEqual(composer.mail_server_id.id, False)
|
||||
self.assertEqual(composer.record_name, 'CustomName')
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_mail_composer_recipients(self):
|
||||
""" Test content management (partner_ids, reply_to) in both comment and
|
||||
mass mailing mode. Template update is also tested. Add some tests for
|
||||
partner creation based on unknown emails as this is part of the process. """
|
||||
base_recipients = self.partner_1 + self.partner_2
|
||||
self.template.write({
|
||||
'email_cc': 'test.cc.1@test.example.com, test.cc.2@test.example.com'
|
||||
})
|
||||
|
||||
for composition_mode in ['comment', 'mass_mail']:
|
||||
self.assertFalse(
|
||||
self.env['res.partner'].search([
|
||||
('email_normalized', 'in', ['test.cc.1@test.example.com',
|
||||
'test.cc.2@test.example.com'])
|
||||
])
|
||||
)
|
||||
if composition_mode == 'comment':
|
||||
ctx = self._get_web_context(self.test_record, add_web=False)
|
||||
else:
|
||||
ctx = self._get_web_context(self.test_records, add_web=False)
|
||||
|
||||
# 1. check without template + template update
|
||||
composer = self.env['mail.compose.message'].with_context(ctx).create({
|
||||
'body': '<p>Test Body</p>',
|
||||
'partner_ids': base_recipients.ids,
|
||||
'reply_to': False,
|
||||
'subject': 'My amazing subject',
|
||||
})
|
||||
|
||||
# creation values are taken
|
||||
self.assertEqual(composer.partner_ids, base_recipients)
|
||||
self.assertFalse(composer.reply_to)
|
||||
self.assertFalse(composer.reply_to_force_new)
|
||||
self.assertEqual(composer.reply_to_mode, 'update')
|
||||
|
||||
# changing template should update its content
|
||||
composer.write({'template_id': self.template.id})
|
||||
# currently onchange necessary
|
||||
composer._onchange_template_id_wrapper()
|
||||
new_partners = self.env['res.partner'].search(
|
||||
[('email_normalized', 'in', ['test.cc.1@test.example.com',
|
||||
'test.cc.2@test.example.com'])
|
||||
]
|
||||
)
|
||||
|
||||
# values come from template
|
||||
if composition_mode == 'comment':
|
||||
self.assertEqual(len(new_partners), 2)
|
||||
self.assertEqual(composer.partner_ids, self.partner_1 + new_partners, 'Template took customer_id as set on record')
|
||||
self.assertEqual(composer.reply_to, 'info@test.example.com', 'Template was rendered')
|
||||
self.assertFalse(composer.reply_to_force_new) # should not change in comment mode
|
||||
else:
|
||||
self.assertEqual(len(new_partners), 0)
|
||||
self.assertEqual(composer.partner_ids, base_recipients, 'Mass mode: kept original values')
|
||||
self.assertEqual(composer.reply_to, self.template.reply_to, 'Mass mode: raw template value')
|
||||
self.assertFalse(composer.reply_to_force_new) # should probably become True, not supported currently
|
||||
|
||||
# manual values is kept over template
|
||||
composer.write({'partner_ids': [(5, 0), (4, self.partner_admin.id)]})
|
||||
self.assertEqual(composer.partner_ids, self.partner_admin)
|
||||
|
||||
# reset template should reset values
|
||||
composer.write({'template_id': False})
|
||||
# currently onchange necessary
|
||||
composer._onchange_template_id_wrapper()
|
||||
|
||||
# values are kepts, not sure why
|
||||
if composition_mode == 'comment':
|
||||
self.assertEqual(composer.partner_ids, self.partner_admin, 'Values are kept, not sure why')
|
||||
self.assertEqual(composer.reply_to, 'info@test.example.com', 'Values are kept')
|
||||
self.assertFalse(composer.reply_to_force_new)
|
||||
else:
|
||||
self.assertEqual(composer.partner_ids, self.partner_admin, 'Mass mode: kept current value')
|
||||
self.assertEqual(composer.reply_to, '{{ ctx.get("custom_reply_to") or "info@test.example.com" }}', 'Mass mode: kept current value')
|
||||
self.assertFalse(composer.reply_to_force_new)
|
||||
|
||||
# 2. check with default
|
||||
ctx['default_template_id'] = self.template.id
|
||||
composer = self.env['mail.compose.message'].with_context(ctx).create({
|
||||
'template_id': self.template.id,
|
||||
})
|
||||
# currently onchange necessary
|
||||
composer._onchange_template_id_wrapper()
|
||||
|
||||
# values come from template
|
||||
if composition_mode == 'comment':
|
||||
self.assertEqual(composer.partner_ids, self.partner_1 + new_partners)
|
||||
else:
|
||||
self.assertFalse(composer.partner_ids)
|
||||
if composition_mode == 'comment':
|
||||
self.assertEqual(composer.reply_to, "info@test.example.com")
|
||||
else:
|
||||
self.assertEqual(composer.reply_to, self.template.reply_to)
|
||||
self.assertFalse(composer.reply_to_force_new) # note: this should be updated with reply-to
|
||||
self.assertEqual(composer.reply_to_mode, 'update') # note: this should be updated with reply-to
|
||||
|
||||
# 3. check at create
|
||||
ctx.pop('default_template_id')
|
||||
composer = self.env['mail.compose.message'].with_context(ctx).create({
|
||||
'template_id': self.template.id,
|
||||
})
|
||||
# currently onchange necessary
|
||||
composer._onchange_template_id_wrapper()
|
||||
|
||||
# values come from template
|
||||
if composition_mode == 'comment':
|
||||
self.assertEqual(composer.partner_ids, self.partner_1 + new_partners)
|
||||
else:
|
||||
self.assertFalse(composer.partner_ids)
|
||||
if composition_mode == 'comment':
|
||||
self.assertEqual(composer.reply_to, "info@test.example.com")
|
||||
else:
|
||||
self.assertEqual(composer.reply_to, self.template.reply_to)
|
||||
self.assertFalse(composer.reply_to_force_new)
|
||||
self.assertEqual(composer.reply_to_mode, 'update')
|
||||
|
||||
# 4. template + user input
|
||||
ctx['default_template_id'] = self.template.id
|
||||
composer = self.env['mail.compose.message'].with_context(ctx).create({
|
||||
'body': '<p>Test Body</p>',
|
||||
'partner_ids': base_recipients.ids,
|
||||
'subject': 'My amazing subject',
|
||||
'reply_to': False,
|
||||
})
|
||||
|
||||
# creation values are taken
|
||||
self.assertEqual(composer.partner_ids, base_recipients)
|
||||
self.assertFalse(composer.reply_to)
|
||||
self.assertFalse(composer.reply_to_force_new)
|
||||
self.assertEqual(composer.reply_to_mode, 'update')
|
||||
|
||||
self.env['res.partner'].search([
|
||||
('email_normalized', 'in', ['test.cc.1@test.example.com',
|
||||
'test.cc.2@test.example.com'])
|
||||
]).unlink()
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
def test_mail_composer_parent(self):
|
||||
""" Test specific management in comment mode when having parent_id set:
|
||||
record_name, subject, parent's partners. """
|
||||
@@ -397,11 +606,13 @@ class TestComposerInternals(TestMailComposer):
|
||||
})
|
||||
|
||||
# creation values taken from parent
|
||||
self.assertEqual(composer.subject, 'Re: %s' % self.test_record.name)
|
||||
self.assertEqual(composer.body, '<p>Test Body</p>')
|
||||
self.assertEqual(composer.partner_ids, self.partner_1 + self.partner_2)
|
||||
self.assertEqual(composer.record_name, self.test_record.name)
|
||||
self.assertEqual(composer.subject, 'Re: %s' % self.test_record.name)
|
||||
|
||||
@users('user_rendering_restricted')
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
def test_mail_composer_rights_attachments(self):
|
||||
""" Ensure a user without write access to a template can send an email"""
|
||||
template_1 = self.template.copy({
|
||||
@@ -437,9 +648,13 @@ class TestComposerInternals(TestMailComposer):
|
||||
sorted(self.test_record.message_ids[0].attachment_ids.mapped('name')),
|
||||
sorted(template_1_attachment_name))
|
||||
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
def test_mail_composer_rights_portal(self):
|
||||
portal_user = self._create_portal_user()
|
||||
# give read access to the record to portal (for check access rule)
|
||||
self.test_record.message_subscribe(partner_ids=portal_user.partner_id.ids)
|
||||
|
||||
# patch check access rights for write access, required to post a message by default
|
||||
with patch.object(MailTestTicket, 'check_access_rights', return_value=True):
|
||||
self.env['mail.compose.message'].with_user(portal_user).with_context(
|
||||
self._get_web_context(self.test_record)
|
||||
@@ -487,7 +702,7 @@ class TestComposerResultsComment(TestMailComposer):
|
||||
notification and emails generated during this process. """
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail')
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
def test_mail_composer_notifications_delete(self):
|
||||
""" Notifications are correctly deleted once sent """
|
||||
composer = self.env['mail.compose.message'].with_context(
|
||||
@@ -504,9 +719,29 @@ class TestComposerResultsComment(TestMailComposer):
|
||||
self.assertEqual(message.notified_partner_ids, self.partner_employee_2 + self.partner_1 + self.partner_2)
|
||||
|
||||
# global outgoing
|
||||
self.assertEqual(len(self._new_mails), 2, 'Should have created 2 mail.mail (1 for users, 1 for customers)')
|
||||
self.assertEqual(len(self._mails), 3, 'Should have sent an email each recipient')
|
||||
self.assertEqual(self._new_mails.exists(), self.env['mail.mail'], 'Should have deleted mail.mail records')
|
||||
self.assertEqual(len(self._new_mails), 2, 'Should have created 2 mail.mail (1 for users, 1 for customers)')
|
||||
self.assertFalse(self._new_mails.exists(), 'Should have deleted mail.mail records')
|
||||
|
||||
# Check ``auto_delete`` field usage (note: currently not correctly managed)
|
||||
composer = self.env['mail.compose.message'].with_context(
|
||||
self._get_web_context(self.test_record),
|
||||
).create({
|
||||
'auto_delete': False,
|
||||
'body': '<p>Test Body</p>',
|
||||
'partner_ids': [(4, self.partner_1.id), (4, self.partner_2.id)]
|
||||
})
|
||||
with self.mock_mail_gateway(mail_unlink_sent=True):
|
||||
composer._action_send_mail()
|
||||
|
||||
# notifications
|
||||
message = self.test_record.message_ids[0]
|
||||
self.assertEqual(message.notified_partner_ids, self.partner_employee_2 + self.partner_1 + self.partner_2)
|
||||
|
||||
# global outgoing
|
||||
self.assertEqual(len(self._mails), 3, 'Should have sent an email each recipient')
|
||||
self.assertEqual(len(self._new_mails), 2, 'Should have created 2 mail.mail (1 for users, 1 for customers)')
|
||||
self.assertEqual(len(self._new_mails.exists()), 0, 'To fix: does not respect auto_delete')
|
||||
|
||||
# ensure ``mail_auto_delete`` context key allow to override this behavior
|
||||
composer = self.env['mail.compose.message'].with_context(
|
||||
@@ -524,12 +759,12 @@ class TestComposerResultsComment(TestMailComposer):
|
||||
self.assertEqual(message.notified_partner_ids, self.partner_employee_2 + self.partner_1 + self.partner_2)
|
||||
|
||||
# global outgoing
|
||||
self.assertEqual(len(self._new_mails), 2, 'Should have created 2 mail.mail (1 for users, 1 for customers)')
|
||||
self.assertEqual(len(self._mails), 3, 'Should have sent an email each recipient')
|
||||
self.assertEqual(len(self._new_mails), 2, 'Should have created 2 mail.mail (1 for users, 1 for customers)')
|
||||
self.assertEqual(len(self._new_mails.exists()), 2, 'Should not have deleted mail.mail records')
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail')
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
def test_mail_composer_recipients(self):
|
||||
""" Test partner_ids given to composer are given to the final message. """
|
||||
composer = self.env['mail.compose.message'].with_context(
|
||||
@@ -541,8 +776,8 @@ class TestComposerResultsComment(TestMailComposer):
|
||||
composer._action_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.body, '<p>Test Body</p>')
|
||||
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)
|
||||
@@ -607,10 +842,11 @@ class TestComposerResultsComment(TestMailComposer):
|
||||
email_values={
|
||||
'body_content': 'TemplateBody %s' % self.test_record.name,
|
||||
'email_from': self.test_record.user_id.email_formatted, # set by template
|
||||
'mail_server_id': self.mail_server_domain,
|
||||
'subject': 'TemplateSubject %s' % self.test_record.name,
|
||||
'attachments_info': [
|
||||
{'name': '00.txt', 'raw': b'Att00', 'type': 'text/plain'},
|
||||
{'name': '01.txt', 'raw': b'Att01', 'type': 'text/plain'},
|
||||
{'name': 'AttFileName_00.txt', 'raw': b'AttContent_00', 'type': 'text/plain'},
|
||||
{'name': 'AttFileName_01.txt', 'raw': b'AttContent_01', 'type': 'text/plain'},
|
||||
{'name': 'TestReport for %s.html' % self.test_record.name, 'type': 'text/plain'},
|
||||
]
|
||||
},
|
||||
@@ -622,10 +858,11 @@ class TestComposerResultsComment(TestMailComposer):
|
||||
email_values={
|
||||
'body_content': 'TemplateBody %s' % self.test_record.name,
|
||||
'email_from': self.test_record.user_id.email_formatted, # set by template
|
||||
'mail_server_id': self.mail_server_domain,
|
||||
'subject': 'TemplateSubject %s' % self.test_record.name,
|
||||
'attachments_info': [
|
||||
{'name': '00.txt', 'raw': b'Att00', 'type': 'text/plain'},
|
||||
{'name': '01.txt', 'raw': b'Att01', 'type': 'text/plain'},
|
||||
{'name': 'AttFileName_00.txt', 'raw': b'AttContent_00', 'type': 'text/plain'},
|
||||
{'name': 'AttFileName_01.txt', 'raw': b'AttContent_01', 'type': 'text/plain'},
|
||||
{'name': 'TestReport for %s.html' % self.test_record.name, 'type': 'text/plain'},
|
||||
]
|
||||
},
|
||||
@@ -638,7 +875,7 @@ class TestComposerResultsComment(TestMailComposer):
|
||||
# attachments are copied on message and linked to document
|
||||
self.assertEqual(
|
||||
set(message.attachment_ids.mapped('name')),
|
||||
set(['00.txt', '01.txt', 'TestReport for %s.html' % self.test_record.name])
|
||||
set(['AttFileName_00.txt', 'AttFileName_01.txt', 'TestReport for %s.html' % self.test_record.name])
|
||||
)
|
||||
self.assertEqual(set(message.attachment_ids.mapped('res_model')), set([self.test_record._name]))
|
||||
self.assertEqual(set(message.attachment_ids.mapped('res_id')), set(self.test_record.ids))
|
||||
@@ -656,10 +893,73 @@ class TestComposerResultsMass(TestMailComposer):
|
||||
'groups_id': [(4, cls.env.ref('base.group_partner_manager').id)],
|
||||
})
|
||||
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
def test_mail_composer_delete(self):
|
||||
""" Check mail / msg delete support """
|
||||
# ensure initial data
|
||||
self.assertTrue(self.template.auto_delete)
|
||||
self.assertEqual(self.test_records.user_id, self.user_employee_2)
|
||||
self.assertEqual(self.test_records.message_partner_ids, self.partner_employee_2)
|
||||
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(
|
||||
self._get_web_context(self.test_records, add_web=True,
|
||||
default_template_id=self.template.id)
|
||||
))
|
||||
composer = composer_form.save()
|
||||
with self.mock_mail_gateway(mail_unlink_sent=True), self.mock_mail_app():
|
||||
composer._action_send_mail()
|
||||
|
||||
self.assertEqual(len(self._mails), 2, 'Should have sent 1 email per record')
|
||||
self.assertEqual(len(self._new_mails), 2, 'Should have created 1 mail.mail per record')
|
||||
self.assertFalse(self._new_mails.exists(), 'Should have deleted mail.mail records')
|
||||
self.assertEqual(len(self._new_msgs), 2, 'Should have created 1 mail.mail per record')
|
||||
self.assertEqual(self._new_msgs.exists(), self._new_msgs, 'Should not have deleted mail.message records')
|
||||
|
||||
# force composer auto_delete field
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(
|
||||
self._get_web_context(self.test_records, add_web=True,
|
||||
default_template_id=self.template.id)
|
||||
))
|
||||
composer = composer_form.save()
|
||||
composer.auto_delete = False
|
||||
with self.mock_mail_gateway(mail_unlink_sent=True), self.mock_mail_app():
|
||||
composer._action_send_mail()
|
||||
|
||||
self.assertEqual(len(self._mails), 2, 'Should have sent 1 email per record')
|
||||
self.assertEqual(len(self._new_mails), 2, 'Should have created 1 mail.mail per record')
|
||||
# self.assertEqual(self._new_mails.exists(), self._new_mails, 'Should not have deleted mail.mail records')
|
||||
self.assertFalse(self._new_mails.exists(), 'Template is forced over composer value, which is not correct')
|
||||
self.assertEqual(len(self._new_msgs), 2, 'Should have created 1 mail.mail per record')
|
||||
self.assertEqual(self._new_msgs.exists(), self._new_msgs, 'Should not have deleted mail.message records')
|
||||
|
||||
# check composer auto_delete_message
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(
|
||||
self._get_web_context(self.test_records, add_web=True,
|
||||
default_template_id=self.template.id)
|
||||
))
|
||||
composer = composer_form.save()
|
||||
composer.auto_delete_message = True
|
||||
with self.mock_mail_gateway(mail_unlink_sent=True), self.mock_mail_app():
|
||||
composer._action_send_mail()
|
||||
|
||||
# global outgoing
|
||||
self.assertEqual(len(self._mails), 2, 'Should have sent 1 email per record')
|
||||
self.assertEqual(len(self._new_mails), 2, 'Should have created 1 mail.mail per record')
|
||||
self.assertFalse(self._new_mails.exists(), 'Should have deleted mail.mail records')
|
||||
self.assertEqual(len(self._new_msgs), 2, 'Should have created 1 mail.mail per record')
|
||||
self.assertFalse(self._new_msgs.exists(), 'Should have deleted mail.message records')
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
|
||||
def test_mail_composer_wtpl(self):
|
||||
self.template.auto_delete = False # keep sent emails to check content
|
||||
|
||||
# ensure initial data
|
||||
self.assertEqual(self.test_records.user_id, self.user_employee_2)
|
||||
self.assertEqual(self.test_records.message_partner_ids, self.partner_employee_2)
|
||||
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(
|
||||
self._get_web_context(self.test_records, add_web=True,
|
||||
default_template_id=self.template.id)
|
||||
@@ -679,15 +979,18 @@ class TestComposerResultsMass(TestMailComposer):
|
||||
# template is sent directly using customer field, meaning we have recipients
|
||||
self.assertMailMail(record.customer_id, 'sent',
|
||||
mail_message=message,
|
||||
author=self.partner_employee)
|
||||
author=self.partner_employee,
|
||||
email_values={
|
||||
'email_from': self.partner_employee_2.email_formatted,
|
||||
})
|
||||
|
||||
# message content
|
||||
self.assertEqual(message.subject, 'TemplateSubject %s' % record.name)
|
||||
self.assertEqual(message.body, '<p>TemplateBody %s</p>' % record.name)
|
||||
self.assertEqual(message.author_id, self.user_employee.partner_id)
|
||||
# post-related fields are void
|
||||
self.assertEqual(message.subtype_id, self.env['mail.message.subtype'])
|
||||
self.assertEqual(message.partner_ids, self.env['res.partner'])
|
||||
self.assertFalse(message.subtype_id)
|
||||
self.assertFalse(message.partner_ids)
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
|
||||
@@ -712,8 +1015,8 @@ class TestComposerResultsMass(TestMailComposer):
|
||||
self.assertEqual(len(attachs), 2)
|
||||
|
||||
# ensure initial data
|
||||
self.assertEqual(self.test_records.user_id, self.env['res.users'])
|
||||
self.assertEqual(self.test_records.message_partner_ids, self.env['res.partner'])
|
||||
self.assertEqual(self.test_records.user_id, self.user_employee_2)
|
||||
self.assertEqual(self.test_records.message_partner_ids, self.partner_employee_2)
|
||||
|
||||
# launch composer in mass mode
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(
|
||||
@@ -752,72 +1055,17 @@ class TestComposerResultsMass(TestMailComposer):
|
||||
author=self.partner_employee,
|
||||
email_values={
|
||||
'body_content': 'TemplateBody %s' % record.name,
|
||||
'email_from': self.partner_employee_2.email_formatted,
|
||||
'mail_server_id': self.mail_server_global.id,
|
||||
'subject': 'TemplateSubject %s' % record.name,
|
||||
# 'attachments': [
|
||||
# ('00.txt', b'Att00', 'text/plain'),
|
||||
# ('01.txt', b'Att01', 'text/plain'),
|
||||
# ('report.test_mail.mail_test_ticket_test_template.html', b'My second attachment', 'text/plain')
|
||||
# ]
|
||||
'attachments_info': [
|
||||
{'name': 'AttFileName_00.txt', 'raw': b'AttContent_00', 'type': 'text/plain'},
|
||||
{'name': 'AttFileName_01.txt', 'raw': b'AttContent_01', 'type': 'text/plain'},
|
||||
{'name': 'TestReport for %s.html' % record.name, 'type': 'text/plain'},
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
|
||||
def test_mail_composer_wtpl_delete(self):
|
||||
self.template.auto_delete = True
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(
|
||||
self._get_web_context(self.test_records, add_web=True,
|
||||
default_template_id=self.template.id)
|
||||
))
|
||||
composer = composer_form.save()
|
||||
with self.mock_mail_gateway(mail_unlink_sent=True):
|
||||
composer._action_send_mail()
|
||||
|
||||
# global outgoing
|
||||
self.assertEqual(len(self._new_mails), 2, 'Should have created 1 mail.mail per record')
|
||||
self.assertEqual(len(self._mails), 2, 'Should have sent 1 email per record')
|
||||
self.assertEqual(self._new_mails.exists(), self.env['mail.mail'], 'Should have deleted mail.mail records')
|
||||
|
||||
for record in self.test_records:
|
||||
# message copy is kept
|
||||
message = record.message_ids[0]
|
||||
|
||||
# template is sent directly using customer field
|
||||
self.assertSentEmail(self.partner_employee, record.customer_id)
|
||||
|
||||
# message content
|
||||
self.assertEqual(message.subject, 'TemplateSubject %s' % record.name)
|
||||
self.assertEqual(message.body, '<p>TemplateBody %s</p>' % record.name)
|
||||
self.assertEqual(message.author_id, self.user_employee.partner_id)
|
||||
# post-related fields are void
|
||||
self.assertEqual(message.subtype_id, self.env['mail.message.subtype'])
|
||||
self.assertEqual(message.partner_ids, self.env['res.partner'])
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
|
||||
def test_mail_composer_wtpl_delete_notif(self):
|
||||
self.template.auto_delete = True
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(
|
||||
self._get_web_context(self.test_records, add_web=True,
|
||||
default_template_id=self.template.id,
|
||||
default_auto_delete_message=True)
|
||||
))
|
||||
composer = composer_form.save()
|
||||
with self.mock_mail_gateway(mail_unlink_sent=True):
|
||||
composer._action_send_mail()
|
||||
|
||||
# global outgoing
|
||||
self.assertEqual(len(self._new_mails), 2, 'Should have created 1 mail.mail per record')
|
||||
self.assertEqual(len(self._mails), 2, 'Should have sent 1 email per record')
|
||||
self.assertEqual(self._new_mails.exists(), self.env['mail.mail'], 'Should have deleted mail.mail records')
|
||||
|
||||
for record in self.test_records:
|
||||
# message copy is unlinked
|
||||
self.assertEqual(record.message_ids, self.env['mail.message'], 'Should have deleted mail.message records')
|
||||
|
||||
# template is sent directly using customer field
|
||||
self.assertSentEmail(self.partner_employee, record.customer_id)
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
|
||||
def test_mail_composer_wtpl_recipients(self):
|
||||
@@ -841,7 +1089,8 @@ class TestComposerResultsMass(TestMailComposer):
|
||||
|
||||
for record in self.test_records:
|
||||
# template is sent directly using customer field
|
||||
self.assertSentEmail(self.partner_employee, record.customer_id)
|
||||
self.assertSentEmail(self.partner_employee_2.email_formatted, record.customer_id,
|
||||
author_id=self.partner_employee)
|
||||
|
||||
# 2: active_domain not taken into account if use_active_domain is False
|
||||
composer_form = Form(self.env['mail.compose.message'].with_context(
|
||||
|
||||
@@ -12,7 +12,6 @@ class TestMailComposerMixin(TestMailCommon, TestRecipients):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMailComposerMixin, cls).setUpClass()
|
||||
cls._init_mail_gateway()
|
||||
|
||||
cls.mail_template = cls.env['mail.template'].create({
|
||||
'subject': 'Subject for {{ object.name }}',
|
||||
|
||||
@@ -14,7 +14,6 @@ class BaseFollowersTest(TestMailCommon):
|
||||
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()
|
||||
|
||||
# allow employee to update partners
|
||||
cls.user_employee.write({'groups_id': [(4, cls.env.ref('base.group_partner_manager').id)]})
|
||||
|
||||
@@ -247,8 +247,6 @@ class TestMailgateway(TestMailCommon):
|
||||
'message_id': '<123456-openerp-%s-mail.test.gateway@%s>' % (cls.test_record.id, socket.gethostname()),
|
||||
})
|
||||
|
||||
cls._init_mail_gateway()
|
||||
|
||||
# --------------------------------------------------
|
||||
# Base low-level tests
|
||||
# --------------------------------------------------
|
||||
@@ -1277,8 +1275,6 @@ class TestMailThreadCC(TestMailCommon):
|
||||
'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',
|
||||
|
||||
@@ -2,22 +2,25 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import psycopg2
|
||||
import smtplib
|
||||
|
||||
from OpenSSL.SSL import Error as SSLError
|
||||
from socket import gaierror, timeout
|
||||
from unittest.mock import call
|
||||
|
||||
from odoo import api
|
||||
from odoo.addons.base.tests.common import MockSmtplibCase
|
||||
from odoo.addons.base.models.ir_mail_server import MailDeliveryException
|
||||
from odoo.addons.test_mail.tests.common import TestMailCommon
|
||||
from odoo.tests import common, tagged
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
@tagged('mail_mail')
|
||||
class TestMailMail(TestMailCommon, MockSmtplibCase):
|
||||
class TestMailMail(TestMailCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMailMail, cls).setUpClass()
|
||||
cls._init_mail_gateway()
|
||||
cls._init_mail_servers()
|
||||
|
||||
cls.server_domain_2 = cls.env['ir.mail_server'].create({
|
||||
@@ -31,9 +34,36 @@ class TestMailMail(TestMailCommon, MockSmtplibCase):
|
||||
'email_from': 'ignasse@example.com',
|
||||
}).with_context({})
|
||||
|
||||
cls.test_message = cls.test_record.message_post(body='<p>Message</p>', subject='Subject')
|
||||
cls.test_mail = cls.env['mail.mail'].create([{
|
||||
'body': '<p>Body</p>',
|
||||
'email_from': False,
|
||||
'email_to': 'test@example.com',
|
||||
'is_notification': True,
|
||||
'subject': 'Subject',
|
||||
}])
|
||||
cls.test_notification = cls.env['mail.notification'].create({
|
||||
'is_read': False,
|
||||
'mail_mail_id': cls.test_mail.id,
|
||||
'mail_message_id': cls.test_message.id,
|
||||
'notification_type': 'email',
|
||||
'res_partner_id': cls.partner_employee.id, # not really used for matching except multi-recipients
|
||||
})
|
||||
|
||||
cls.emails_falsy = [False, '', ' ']
|
||||
cls.emails_invalid = ['buggy', 'buggy, wrong']
|
||||
cls.emails_invalid_ascii = ['raoul@example¢¡.com']
|
||||
cls.emails_valid = ['raoul¢¡@example.com', 'raoul@example.com']
|
||||
|
||||
def _reset_data(self):
|
||||
self._init_mail_mock()
|
||||
self.test_mail.write({'failure_reason': False, 'failure_type': False, 'state': 'outgoing'})
|
||||
self.test_notification.write({'failure_type': False, 'notification_status': 'ready'})
|
||||
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_mail_message_notify_from_mail_mail(self):
|
||||
# Due ot post-commit hooks, store send emails in every step
|
||||
def test_mail_mail_recipients(self):
|
||||
""" Partner_ids is a field used from mail_message, but not from mail_mail. """
|
||||
mail = self.env['mail.mail'].sudo().create({
|
||||
'body_html': '<p>Test</p>',
|
||||
'email_to': 'test@example.com',
|
||||
@@ -44,6 +74,18 @@ class TestMailMail(TestMailCommon, MockSmtplibCase):
|
||||
self.assertSentEmail(mail.env.user.partner_id, ['test@example.com'])
|
||||
self.assertEqual(len(self._mails), 1)
|
||||
|
||||
mail = self.env['mail.mail'].sudo().create({
|
||||
'body_html': '<p>Test</p>',
|
||||
'email_to': 'test@example.com',
|
||||
'recipient_ids': [(4, self.user_employee.partner_id.id)],
|
||||
})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send()
|
||||
self.assertSentEmail(mail.env.user.partner_id, ['test@example.com'])
|
||||
self.assertSentEmail(mail.env.user.partner_id, [self.user_employee.email_formatted])
|
||||
self.assertEqual(len(self._mails), 2)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_mail_mail_return_path(self):
|
||||
# mail without thread-enabled record
|
||||
base_values = {
|
||||
@@ -65,6 +107,354 @@ class TestMailMail(TestMailCommon, MockSmtplibCase):
|
||||
mail.send()
|
||||
self.assertEqual(self._mails[0]['headers']['Return-Path'], '%s@%s' % (self.alias_bounce, self.alias_domain))
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_mail_mail_send_exceptions_origin(self):
|
||||
""" Test various use case with exceptions and errors and see how they are
|
||||
managed and stored at mail and notification level. """
|
||||
mail, notification = self.test_mail, self.test_notification
|
||||
|
||||
# MailServer.build_email(): invalid from
|
||||
self.env['ir.config_parameter'].set_param('mail.default.from', '')
|
||||
self._reset_data()
|
||||
with self.mock_mail_gateway(), mute_logger('odoo.addons.mail.models.mail_mail'):
|
||||
mail.send(raise_exception=False)
|
||||
self.assertFalse(self._mails[0]['email_from'])
|
||||
self.assertIn(
|
||||
'You must either provide a sender address explicitly or configure using the combination of `mail.catchall.domain` and `mail.default.from` ICPs',
|
||||
mail.failure_reason)
|
||||
self.assertFalse(mail.failure_type, 'Mail: void from: no failure type, should be updated')
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
self.assertEqual(notification.failure_type, 'unknown', 'Mail: void from: unknown failure type, should be updated')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
|
||||
# MailServer.send_email(): _prepare_email_message: unexpected ASCII
|
||||
# Force catchall domain to void otherwise bounce is set to postmaster-odoo@domain
|
||||
self.env['ir.config_parameter'].set_param('mail.catchall.domain', '')
|
||||
self._reset_data()
|
||||
mail.write({'email_from': 'strange@example¢¡.com'})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertEqual(self._mails[0]['email_from'], 'strange@example¢¡.com')
|
||||
self.assertIn('Codepoint U+00A2 at position', mail.failure_reason)
|
||||
self.assertFalse(mail.failure_type, 'Mail: bugged from (ascii): no failure type, should be updated')
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
self.assertEqual(notification.failure_type, 'unknown', 'Mail: bugged from (ascii): unknown failure type, should be updated')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
|
||||
# MailServer.send_email(): _prepare_email_message: unexpected ASCII based on catchall domain
|
||||
self.env['ir.config_parameter'].set_param('mail.catchall.domain', 'domain¢¡.com')
|
||||
self._reset_data()
|
||||
mail.write({'email_from': 'test.user@example.com'})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertEqual(self._mails[0]['email_from'], 'test.user@example.com')
|
||||
self.assertIn('Codepoint U+00A2 at position', mail.failure_reason)
|
||||
self.assertFalse(mail.failure_type, 'Mail: bugged catchall domain (ascii): no failure type, should be updated')
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
self.assertEqual(notification.failure_type, 'unknown', 'Mail: bugged catchall domain (ascii): unknown failure type, should be updated')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
|
||||
# MailServer.send_email(): _prepare_email_message: Malformed 'Return-Path' or 'From' address
|
||||
self.env['ir.config_parameter'].set_param('mail.catchall.domain', '')
|
||||
self._reset_data()
|
||||
mail.write({'email_from': 'robert'})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertEqual(self._mails[0]['email_from'], 'robert')
|
||||
self.assertIn("Malformed 'Return-Path' or 'From' address: robert", mail.failure_reason)
|
||||
self.assertFalse(mail.failure_type, 'Mail: bugged from (ascii): no failure type, should be updated')
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
self.assertEqual(notification.failure_type, 'unknown', 'Mail: bugged from (ascii): unknown failure type, should be updated')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_mail_mail_send_exceptions_recipients_emails(self):
|
||||
""" Test various use case with exceptions and errors and see how they are
|
||||
managed and stored at mail and notification level. """
|
||||
mail, notification = self.test_mail, self.test_notification
|
||||
|
||||
self.env['ir.config_parameter'].set_param('mail.catchall.domain', self.alias_domain)
|
||||
self.env['ir.config_parameter'].set_param('mail.default.from', self.default_from)
|
||||
|
||||
# MailServer.send_email(): _prepare_email_message: missing To
|
||||
for email_to in self.emails_falsy:
|
||||
self._reset_data()
|
||||
mail.write({'email_to': email_to})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertIn('Error without exception. Probably due do sending an email without computed recipients.', mail.failure_reason)
|
||||
self.assertFalse(mail.failure_type, 'Mail: missing email_to: no failure type, should be updated')
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
if email_to == ' ':
|
||||
self.assertEqual(notification.failure_type, 'mail_email_missing')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
else:
|
||||
self.assertEqual(notification.failure_type, False, 'Mail: missing email_to: notification is wrongly set as sent')
|
||||
self.assertEqual(notification.notification_status, 'sent', 'Mail: missing email_to: notification is wrongly set as sent')
|
||||
|
||||
# MailServer.send_email(): _prepare_email_message: invalid To
|
||||
for email_to, failure_type in zip(self.emails_invalid,
|
||||
['mail_email_missing', 'mail_email_missing']):
|
||||
self._reset_data()
|
||||
mail.write({'email_to': email_to})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertIn('Error without exception. Probably due do sending an email without computed recipients.', mail.failure_reason)
|
||||
self.assertFalse(mail.failure_type, 'Mail: invalid email_to: no failure type, should be updated')
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
self.assertEqual(notification.failure_type, failure_type, 'Mail: invalid email_to: missing instead of invalid')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
|
||||
# MailServer.send_email(): _prepare_email_message: invalid To (ascii)
|
||||
for email_to in self.emails_invalid_ascii:
|
||||
self._reset_data()
|
||||
mail.write({'email_to': email_to})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertIn('Codepoint U+00A2 at position', mail.failure_reason)
|
||||
self.assertFalse(mail.failure_type, 'Mail: invalid (ascii) recipient partner: no failure type, should be updated')
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
self.assertEqual(notification.failure_type, 'unknown', 'Mail: invalid (ascii) recipient partner: unknown failure type, should be updated')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
|
||||
# MailServer.send_email(): _prepare_email_message: ok To (ascii or just ok)
|
||||
for email_to in self.emails_valid:
|
||||
self._reset_data()
|
||||
mail.write({'email_to': email_to})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertFalse(mail.failure_reason)
|
||||
self.assertFalse(mail.failure_type)
|
||||
self.assertEqual(mail.state, 'sent')
|
||||
self.assertFalse(notification.failure_type)
|
||||
self.assertEqual(notification.notification_status, 'sent')
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_mail_mail_send_exceptions_recipients_partners(self):
|
||||
""" Test various use case with exceptions and errors and see how they are
|
||||
managed and stored at mail and notification level. """
|
||||
mail, notification = self.test_mail, self.test_notification
|
||||
|
||||
mail.write({'email_from': 'test.user@test.example.com', 'email_to': False})
|
||||
partners_falsy = self.env['res.partner'].create([
|
||||
{'name': 'Name %s' % email, 'email': email}
|
||||
for email in self.emails_falsy
|
||||
])
|
||||
partners_invalid = self.env['res.partner'].create([
|
||||
{'name': 'Name %s' % email, 'email': email}
|
||||
for email in self.emails_invalid
|
||||
])
|
||||
partners_invalid_ascii = self.env['res.partner'].create([
|
||||
{'name': 'Name %s' % email, 'email': email}
|
||||
for email in self.emails_invalid_ascii
|
||||
])
|
||||
partners_valid = self.env['res.partner'].create([
|
||||
{'name': 'Name %s' % email, 'email': email}
|
||||
for email in self.emails_valid
|
||||
])
|
||||
|
||||
# void values
|
||||
for partner in partners_falsy:
|
||||
self._reset_data()
|
||||
mail.write({'recipient_ids': [(5, 0), (4, partner.id)]})
|
||||
notification.write({'res_partner_id': partner.id})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertEqual(mail.failure_reason, 'Error without exception. Probably due do sending an email without computed recipients.')
|
||||
self.assertFalse(mail.failure_type, 'Mail: void recipient partner: no failure type, should be updated')
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
self.assertEqual(notification.failure_type, 'mail_email_invalid', 'Mail: void recipient partner: should be missing, not invalid')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
|
||||
# wrong values
|
||||
for partner in partners_invalid:
|
||||
self._reset_data()
|
||||
mail.write({'recipient_ids': [(5, 0), (4, partner.id)]})
|
||||
notification.write({'res_partner_id': partner.id})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertEqual(mail.failure_reason, 'Error without exception. Probably due do sending an email without computed recipients.')
|
||||
self.assertFalse(mail.failure_type, 'Mail: invalid recipient partner: no failure type, should be updated')
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
self.assertEqual(notification.failure_type, 'mail_email_invalid')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
|
||||
# ascii ko
|
||||
for partner in partners_invalid_ascii:
|
||||
self._reset_data()
|
||||
mail.write({'recipient_ids': [(5, 0), (4, partner.id)]})
|
||||
notification.write({'res_partner_id': partner.id})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertIn('Codepoint U+00A2 at position', mail.failure_reason)
|
||||
self.assertFalse(mail.failure_type, 'Mail: invalid (ascii) recipient partner: no failure type, should be updated')
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
self.assertEqual(notification.failure_type, 'unknown', 'Mail: invalid (ascii) recipient partner: unknown failure type, should be updated')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
|
||||
# ascii ok or just ok
|
||||
for partner in partners_valid:
|
||||
self._reset_data()
|
||||
mail.write({'recipient_ids': [(5, 0), (4, partner.id)]})
|
||||
notification.write({'res_partner_id': partner.id})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertFalse(mail.failure_reason)
|
||||
self.assertFalse(mail.failure_type)
|
||||
self.assertEqual(mail.state, 'sent')
|
||||
self.assertFalse(notification.failure_type)
|
||||
self.assertEqual(notification.notification_status, 'sent')
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_mail_mail_send_exceptions_recipients_partners_mixed(self):
|
||||
""" Test various use case with exceptions and errors and see how they are
|
||||
managed and stored at mail and notification level. """
|
||||
mail, notification = self.test_mail, self.test_notification
|
||||
|
||||
mail.write({'email_to': 'test@example.com'})
|
||||
partners_falsy = self.env['res.partner'].create([
|
||||
{'name': 'Name %s' % email, 'email': email}
|
||||
for email in self.emails_falsy
|
||||
])
|
||||
partners_invalid = self.env['res.partner'].create([
|
||||
{'name': 'Name %s' % email, 'email': email}
|
||||
for email in self.emails_invalid
|
||||
])
|
||||
partners_valid = self.env['res.partner'].create([
|
||||
{'name': 'Name %s' % email, 'email': email}
|
||||
for email in self.emails_valid
|
||||
])
|
||||
|
||||
# valid to, missing email for recipient or wrong email for recipient
|
||||
for partner in partners_falsy + partners_invalid:
|
||||
self._reset_data()
|
||||
mail.write({'recipient_ids': [(5, 0), (4, partner.id)]})
|
||||
notification.write({'res_partner_id': partner.id})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertFalse(mail.failure_reason, 'Mail: at least one valid recipient, mail is sent to avoid send loops and spam')
|
||||
self.assertFalse(mail.failure_type, 'Mail: at least one valid recipient, mail is sent to avoid send loops and spam')
|
||||
self.assertEqual(mail.state, 'sent', 'Mail: at least one valid recipient, mail is sent to avoid send loops and spam')
|
||||
self.assertEqual(notification.failure_type, 'mail_email_invalid', 'Mail: void email considered as invalid')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
|
||||
# update to have valid partner and invalid partner
|
||||
mail.write({'recipient_ids': [(5, 0), (4, partners_valid[1].id), (4, partners_falsy[0].id)]})
|
||||
notification.write({'res_partner_id': partners_valid[1].id})
|
||||
notification2 = notification.create({
|
||||
'is_read': False,
|
||||
'mail_mail_id': mail.id,
|
||||
'mail_message_id': self.test_message.id,
|
||||
'notification_type': 'email',
|
||||
'res_partner_id': partners_falsy[0].id,
|
||||
})
|
||||
|
||||
# missing to / invalid to
|
||||
for email_to in self.emails_falsy + self.emails_invalid:
|
||||
self._reset_data()
|
||||
notification2.write({'failure_type': False, 'notification_status': 'ready'})
|
||||
mail.write({'email_to': email_to})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertFalse(mail.failure_reason, 'Mail: at least one valid recipient, mail is sent to avoid send loops and spam')
|
||||
self.assertFalse(mail.failure_type, 'Mail: at least one valid recipient, mail is sent to avoid send loops and spam')
|
||||
self.assertEqual(mail.state, 'sent', 'Mail: at least one valid recipient, mail is sent to avoid send loops and spam')
|
||||
self.assertFalse(notification.failure_type)
|
||||
self.assertEqual(notification.notification_status, 'sent')
|
||||
self.assertEqual(notification2.failure_type, 'mail_email_invalid')
|
||||
self.assertEqual(notification2.notification_status, 'exception')
|
||||
|
||||
# buggy to (ascii)
|
||||
for email_to in self.emails_invalid_ascii:
|
||||
self._reset_data()
|
||||
notification2.write({'failure_type': False, 'notification_status': 'ready'})
|
||||
mail.write({'email_to': email_to})
|
||||
with self.mock_mail_gateway():
|
||||
mail.send(raise_exception=False)
|
||||
self.assertIn('Codepoint U+00A2 at position', mail.failure_reason)
|
||||
self.assertFalse(mail.failure_type, 'Mail: at least one valid recipient, mail is sent to avoid send loops and spam')
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
self.assertEqual(notification.failure_type, 'unknown')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
self.assertEqual(notification2.failure_type, 'unknown')
|
||||
self.assertEqual(notification2.notification_status, 'exception')
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_mail_mail_send_exceptions_raise_management(self):
|
||||
""" Test various use case with exceptions and errors and see how they are
|
||||
managed and stored at mail and notification level. """
|
||||
mail, notification = self.test_mail, self.test_notification
|
||||
mail.write({'email_from': 'test.user@test.example.com', 'email_to': 'test@example.com'})
|
||||
|
||||
# SMTP connecting issues
|
||||
with self.mock_mail_gateway():
|
||||
_connect_current = self.connect_mocked.side_effect
|
||||
|
||||
# classic errors that may be raised during sending, just to test their current support
|
||||
for error, msg in [
|
||||
(smtplib.SMTPServerDisconnected('SMTPServerDisconnected'), 'SMTPServerDisconnected'),
|
||||
(smtplib.SMTPResponseException('code', 'SMTPResponseException'), 'code\nSMTPResponseException'),
|
||||
(smtplib.SMTPNotSupportedError('SMTPNotSupportedError'), 'SMTPNotSupportedError'),
|
||||
(smtplib.SMTPException('SMTPException'), 'SMTPException'),
|
||||
(SSLError('SSLError'), 'SSLError'),
|
||||
(gaierror('gaierror'), 'gaierror'),
|
||||
(timeout('timeout'), 'timeout')]:
|
||||
|
||||
def _connect(*args, **kwargs):
|
||||
raise error
|
||||
self.connect_mocked.side_effect = _connect
|
||||
|
||||
mail.send(raise_exception=False)
|
||||
self.assertFalse(mail.failure_type)
|
||||
self.assertEqual(mail.failure_reason, msg)
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
self.assertEqual(notification.failure_type, 'mail_smtp')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
self._reset_data()
|
||||
|
||||
self.connect_mocked.side_effect = _connect_current
|
||||
|
||||
# SMTP sending issues
|
||||
with self.mock_mail_gateway():
|
||||
_send_current = self.send_email_mocked.side_effect
|
||||
self._reset_data()
|
||||
mail.write({'email_to': 'test@example.com'})
|
||||
|
||||
# should always raise for those errors, even with raise_exception=False
|
||||
for error, error_class in [
|
||||
(smtplib.SMTPServerDisconnected("Some exception"), smtplib.SMTPServerDisconnected),
|
||||
(MemoryError("Some exception"), MemoryError)]:
|
||||
def _send_email(*args, **kwargs):
|
||||
raise error
|
||||
self.send_email_mocked.side_effect = _send_email
|
||||
|
||||
with self.assertRaises(error_class):
|
||||
mail.send(raise_exception=False)
|
||||
self.assertFalse(mail.failure_reason, 'SMTPServerDisconnected/MemoryError during Send raises and lead to a rollback')
|
||||
self.assertFalse(mail.failure_type, 'SMTPServerDisconnected/MemoryError during Send raises and lead to a rollback')
|
||||
self.assertEqual(mail.state, 'outgoing', 'SMTPServerDisconnected/MemoryError during Send raises and lead to a rollback')
|
||||
self.assertFalse(notification.failure_type, 'SMTPServerDisconnected/MemoryError during Send raises and lead to a rollback')
|
||||
self.assertEqual(notification.notification_status, 'ready', 'SMTPServerDisconnected/MemoryError during Send raises and lead to a rollback')
|
||||
|
||||
# MailDeliveryException: should be catched; other issues are sub-catched under
|
||||
# a MailDeliveryException and are catched
|
||||
for error, msg in [
|
||||
(MailDeliveryException("Some exception"), 'Some exception'),
|
||||
(ValueError("Unexpected issue"), 'Unexpected issue')]:
|
||||
def _send_email(*args, **kwargs):
|
||||
raise error
|
||||
self.send_email_mocked.side_effect = _send_email
|
||||
|
||||
self._reset_data()
|
||||
mail.send(raise_exception=False)
|
||||
self.assertEqual(mail.failure_reason, msg)
|
||||
self.assertFalse(mail.failure_type, 'Mail: unlogged failure type to fix')
|
||||
self.assertEqual(mail.state, 'exception')
|
||||
self.assertEqual(notification.failure_type, 'unknown', 'Mail: generic failure type')
|
||||
self.assertEqual(notification.notification_status, 'exception')
|
||||
|
||||
self.send_email_mocked.side_effect = _send_current
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_mail_mail_send_server(self):
|
||||
"""Test that the mails are send in batch.
|
||||
@@ -133,6 +523,7 @@ class TestMailMail(TestMailCommon, MockSmtplibCase):
|
||||
self.assert_email_sent_smtp(message_from='user_1@test_2.com', emails_count=5, from_filter=self.server_domain.from_filter)
|
||||
|
||||
|
||||
@tagged('mail_mail')
|
||||
class TestMailMailRace(common.TransactionCase):
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
|
||||
@@ -18,7 +18,6 @@ class TestMessageValues(TestMailCommon):
|
||||
def setUpClass(cls):
|
||||
super(TestMessageValues, cls).setUpClass()
|
||||
|
||||
cls._init_mail_gateway()
|
||||
cls.alias_record = cls.env['mail.test.container'].with_context(cls._test_context).create({
|
||||
'name': 'Pigs',
|
||||
'alias_name': 'pigs',
|
||||
|
||||
@@ -47,8 +47,6 @@ class TestMultiCompanySetup(TestMailCommon, TestRecipients):
|
||||
'message_id': '<123456-openerp-%s-mail.test.gateway@%s>' % (cls.test_record.id, socket.gethostname()),
|
||||
})
|
||||
|
||||
cls._init_mail_gateway()
|
||||
|
||||
@users('employee')
|
||||
def test_notify_reply_to_computation(self):
|
||||
test_record = self.env['mail.test.gateway'].browse(self.test_record.ids)
|
||||
|
||||
@@ -103,6 +103,7 @@ class TestChatterTweaks(TestMailCommon, TestRecipients):
|
||||
self.assertTrue(record.name)
|
||||
|
||||
|
||||
@tagged('mail_thread')
|
||||
class TestDiscuss(TestMailCommon, TestRecipients):
|
||||
|
||||
@classmethod
|
||||
@@ -239,7 +240,12 @@ class TestDiscuss(TestMailCommon, TestRecipients):
|
||||
partner_ids=[self.user_employee.partner_id.id]
|
||||
)
|
||||
self.assertFalse(message.has_error)
|
||||
with self.mock_mail_gateway(sim_error='connect_smtp_notfound'):
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
def _connect(*args, **kwargs):
|
||||
raise Exception("Some exception")
|
||||
self.connect_mocked.side_effect = _connect
|
||||
|
||||
self.user_admin.notification_type = 'email'
|
||||
message2 = self.test_record.with_user(self.user_employee).message_post(
|
||||
body='Test', message_type='comment', subtype_xmlid='mail.mt_comment',
|
||||
|
||||
@@ -34,8 +34,10 @@ class TestMailResend(TestMailCommon):
|
||||
def test_mail_resend_workflow(self):
|
||||
with self.assertSinglePostNotifications(
|
||||
[{'partner': partner, 'type': 'email', 'status': 'exception'} for partner in self.partners],
|
||||
message_info={'message_type': 'notification'},
|
||||
sim_error='connect_failure'):
|
||||
message_info={'message_type': 'notification'}):
|
||||
def _connect(*args, **kwargs):
|
||||
raise Exception("Some exception")
|
||||
self.connect_mocked.side_effect = _connect
|
||||
message = self.test_record.with_user(self.user_admin).message_post(partner_ids=self.partners.ids, subtype_xmlid='mail.mt_comment', message_type='notification')
|
||||
|
||||
wizard = self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({})
|
||||
|
||||
@@ -6,6 +6,7 @@ import base64
|
||||
from unittest.mock import patch
|
||||
|
||||
from odoo import tools
|
||||
from odoo.addons.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.addons.test_mail.tests.common import TestMailCommon, TestRecipients
|
||||
@@ -19,12 +20,29 @@ from markupsafe import escape
|
||||
|
||||
|
||||
@tagged('mail_post')
|
||||
class TestMessagePost(TestMailCommon, TestRecipients):
|
||||
class TestMessagePostCommon(TestMailCommon, TestRecipients):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMessagePost, cls).setUpClass()
|
||||
cls._create_portal_user()
|
||||
super(TestMessagePostCommon, cls).setUpClass()
|
||||
|
||||
# portal user, notably for ACLS / notifications
|
||||
cls.user_portal = cls._create_portal_user()
|
||||
cls.partner_portal = cls.user_portal.partner_id
|
||||
|
||||
# another standard employee to test follow and notifications between two
|
||||
# users (and not admin / user)
|
||||
cls.user_employee_2 = mail_new_test_user(
|
||||
cls.env, login='employee2',
|
||||
groups='base.group_user',
|
||||
company_id=cls.company_admin.id,
|
||||
email='eglantine@example.com', # check: use a formatted email
|
||||
name='Eglantine Employee2',
|
||||
notification_type='email',
|
||||
signature='--\nEglantine',
|
||||
)
|
||||
cls.partner_employee_2 = cls.user_employee_2.partner_id
|
||||
|
||||
cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({
|
||||
'name': 'Test',
|
||||
'email_from': 'ignasse@example.com'
|
||||
@@ -45,8 +63,22 @@ class TestMessagePost(TestMailCommon, TestRecipients):
|
||||
})
|
||||
cls.user_admin.write({'notification_type': 'email'})
|
||||
|
||||
def setUp(self):
|
||||
super(TestMessagePostCommon, self).setUp()
|
||||
# send tracking and messages + patch registry to simulate a ready environment
|
||||
# purpose is to avoid nondeterministic tests, notably because tracking is
|
||||
# accumulated and sent at flush -> we want to test only the result of a
|
||||
# given test, not setup + test
|
||||
self.flush_tracking()
|
||||
# see ``_message_auto_subscribe_notify``
|
||||
self.patch(self.env.registry, 'ready', True)
|
||||
|
||||
|
||||
@tagged('mail_post')
|
||||
class TestMailNotifyAPI(TestMessagePostCommon):
|
||||
|
||||
@users('employee')
|
||||
def test_notify_email_layouts(self):
|
||||
def test_email_notifiction_layouts(self):
|
||||
self.user_employee.write({'notification_type': 'email'})
|
||||
test_record = self.env['mail.test.simple'].browse(self.test_record.ids)
|
||||
test_message = self.env['mail.message'].browse(self.test_message.ids)
|
||||
@@ -74,12 +106,13 @@ class TestMessagePost(TestMailCommon, TestRecipients):
|
||||
self.assertTrue(user_email)
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_notify_by_mail_add_signature(self):
|
||||
self.test_track = self.env['mail.test.track'].with_context(self._test_context).with_user(self.user_employee).create({
|
||||
test_track = self.env['mail.test.track'].with_context(self._test_context).with_user(self.user_employee).create({
|
||||
'name': 'Test',
|
||||
'email_from': 'ignasse@example.com'
|
||||
})
|
||||
self.test_track.user_id = self.env.user
|
||||
test_track.user_id = self.env.user
|
||||
|
||||
signature = self.env.user.signature
|
||||
|
||||
@@ -87,7 +120,7 @@ class TestMessagePost(TestMailCommon, TestRecipients):
|
||||
self.assertIn("record.user_id.sudo().signature", template.arch)
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
self.test_track.message_post(
|
||||
test_track.message_post(
|
||||
body="Test body",
|
||||
email_add_signature=True,
|
||||
email_layout_xmlid="mail.mail_notification_paynow",
|
||||
@@ -99,12 +132,12 @@ class TestMessagePost(TestMailCommon, TestRecipients):
|
||||
self.assertEqual(found_mail.body_html.count(signature), 1)
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
self.test_track.message_post(
|
||||
test_track.message_post(
|
||||
body="Test body",
|
||||
email_add_signature=False,
|
||||
email_layout_xmlid="mail.mail_notification_paynow",
|
||||
mail_auto_delete=False,
|
||||
partner_ids=[self.partner_1.id, self.partner_2.id]
|
||||
partner_ids=[self.partner_1.id, self.partner_2.id],
|
||||
)
|
||||
found_mail = self._new_mails
|
||||
self.assertNotIn(signature, found_mail.body_html)
|
||||
@@ -112,18 +145,22 @@ class TestMessagePost(TestMailCommon, TestRecipients):
|
||||
|
||||
@users('employee')
|
||||
def test_notify_by_email_add_signature_no_author_user_or_no_user(self):
|
||||
self.test_message.author_id = self.env['res.partner'].sudo().create({
|
||||
'name': 'Steve',
|
||||
}).id
|
||||
template_values = self.test_record._notify_by_email_prepare_rendering_context(self.test_message, {})
|
||||
test_record = self.env['mail.test.simple'].browse(self.test_record.ids)
|
||||
test_message = self.env['mail.message'].browse(self.test_message.ids)
|
||||
test_message.write({
|
||||
'author_id': self.env['res.partner'].sudo().create({
|
||||
'name': 'Steve',
|
||||
}).id
|
||||
})
|
||||
template_values = test_record._notify_by_email_prepare_rendering_context(test_message, {})
|
||||
self.assertNotEqual(escape(template_values['signature']), escape('<p>-- <br/>Steve</p>'))
|
||||
|
||||
self.test_message.author_id = None
|
||||
template_values = self.test_record._notify_by_email_prepare_rendering_context(self.test_message, {})
|
||||
template_values = test_record._notify_by_email_prepare_rendering_context(test_message, {})
|
||||
self.assertEqual(template_values['signature'], '')
|
||||
|
||||
@users('employee')
|
||||
def test_notify_by_email_prepare_rendering_contextt(self):
|
||||
def test_notify_by_email_prepare_rendering_context(self):
|
||||
""" Verify that the template context company value is right
|
||||
after switching the env company or if a company_id is set
|
||||
on mail record.
|
||||
@@ -225,300 +262,495 @@ class TestMessagePost(TestMailCommon, TestRecipients):
|
||||
self.assertFalse(partner_info['has_button_access'])
|
||||
self.assertFalse(emp_info['has_button_access'])
|
||||
|
||||
|
||||
@tagged('mail_post', 'mail_notify')
|
||||
class TestMessageNotify(TestMessagePostCommon):
|
||||
|
||||
@users('employee')
|
||||
@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.assertSinglePostNotifications([{'partner': self.partner_employee, 'type': 'inbox'}], {'content': 'Body'}):
|
||||
self.test_record.message_post(
|
||||
body='Body', message_type='comment', subtype_xmlid='mail.mt_comment',
|
||||
partner_ids=[self.user_employee.partner_id.id])
|
||||
|
||||
self.test_record.message_subscribe([self.partner_1.id])
|
||||
with self.assertSinglePostNotifications([
|
||||
{'partner': self.partner_employee, 'type': 'inbox'},
|
||||
{'partner': self.partner_1, 'type': 'email'}], {'content': 'NewBody'}):
|
||||
self.test_record.message_post(
|
||||
body='NewBody', message_type='comment', subtype_xmlid='mail.mt_comment',
|
||||
partner_ids=[self.user_employee.partner_id.id])
|
||||
|
||||
with self.assertSinglePostNotifications([
|
||||
{'partner': self.partner_1, 'type': 'email'},
|
||||
{'partner': self.partner_portal, 'type': 'email'}], {'content': 'ToPortal'}):
|
||||
self.test_record.message_post(
|
||||
body='ToPortal', message_type='comment', subtype_xmlid='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.assertSinglePostNotifications([{'partner': self.partner_employee, 'type': 'inbox'}], {'content': 'Test'}):
|
||||
self.test_record.message_post(
|
||||
body='Test', message_type='comment', subtype_xmlid='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.assertPostNotifications([{'content': 'Test', 'notif': []}]):
|
||||
self.test_record.message_post(
|
||||
body='Test', message_type='comment', subtype_xmlid='mail.mt_comment')
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_post_notifications(self):
|
||||
_body, _subject = '<p>Test Body</p>', 'Test Subject'
|
||||
|
||||
# subscribe second employee to the group to test notifications
|
||||
self.test_record.message_subscribe(partner_ids=[self.user_admin.partner_id.id])
|
||||
|
||||
with self.assertSinglePostNotifications(
|
||||
[{'partner': self.partner_1, 'type': 'email'},
|
||||
{'partner': self.partner_2, 'type': 'email'},
|
||||
{'partner': self.partner_admin, 'type': 'email'}],
|
||||
{'content': _body},
|
||||
mail_unlink_sent=True):
|
||||
msg = self.test_record.with_user(self.user_employee).message_post(
|
||||
body=_body, subject=_subject,
|
||||
message_type='comment', subtype_xmlid='mail.mt_comment',
|
||||
partner_ids=[self.partner_1.id, self.partner_2.id]
|
||||
)
|
||||
|
||||
# message content
|
||||
self.assertEqual(msg.subject, _subject)
|
||||
self.assertEqual(msg.body, _body)
|
||||
self.assertEqual(msg.partner_ids, self.partner_1 | self.partner_2)
|
||||
self.assertEqual(msg.notified_partner_ids, self.user_admin.partner_id | self.partner_1 | self.partner_2)
|
||||
|
||||
# notifications emails should have been deleted
|
||||
self.assertFalse(self.env['mail.mail'].sudo().search([('mail_message_id', '=', msg.id)]),
|
||||
'message_post: mail.mail notifications should have been auto-deleted')
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_post_notifications_keep_emails(self):
|
||||
self.test_record.message_subscribe(partner_ids=[self.user_admin.partner_id.id])
|
||||
|
||||
msg = self.test_record.with_user(self.user_employee).message_post(
|
||||
body='Test', subject='Test',
|
||||
message_type='comment', subtype_xmlid='mail.mt_comment',
|
||||
partner_ids=[self.partner_1.id, self.partner_2.id],
|
||||
mail_auto_delete=False
|
||||
)
|
||||
|
||||
# notifications emails should not have been deleted: one for customers, one for user
|
||||
self.assertEqual(len(self.env['mail.mail'].sudo().search([('mail_message_id', '=', msg.id)])), 2)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_post_notifications_emails_tweak(self):
|
||||
pass
|
||||
# we should check _notification_groups behavior, for emails and buttons
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_post_attachments(self):
|
||||
_attachments = [
|
||||
('List1', b'My first attachment'),
|
||||
('List2', b'My second attachment')
|
||||
]
|
||||
_attach_1 = self.env['ir.attachment'].with_user(self.user_employee).create({
|
||||
'name': 'Attach1',
|
||||
'datas': 'bWlncmF0aW9uIHRlc3Q=',
|
||||
'res_model': 'mail.compose.message', 'res_id': 0})
|
||||
_attach_2 = self.env['ir.attachment'].with_user(self.user_employee).create({
|
||||
'name': 'Attach2',
|
||||
'datas': 'bWlncmF0aW9uIHRlc3Q=',
|
||||
'res_model': 'mail.compose.message', 'res_id': 0})
|
||||
def test_notify(self):
|
||||
test_record = self.env['mail.test.simple'].browse(self.test_record.ids)
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
msg = self.test_record.with_user(self.user_employee).message_post(
|
||||
body='Test', subject='Test',
|
||||
message_type='comment', subtype_xmlid='mail.mt_comment',
|
||||
attachment_ids=[_attach_1.id, _attach_2.id],
|
||||
partner_ids=[self.partner_1.id],
|
||||
attachments=_attachments,
|
||||
)
|
||||
|
||||
# message attachments
|
||||
self.assertEqual(len(msg.attachment_ids), 4)
|
||||
self.assertEqual(set(msg.attachment_ids.mapped('res_model')), set([self.test_record._name]))
|
||||
self.assertEqual(set(msg.attachment_ids.mapped('res_id')), set([self.test_record.id]))
|
||||
self.assertEqual(set([base64.b64decode(x) for x in msg.attachment_ids.mapped('datas')]),
|
||||
set([b'migration test', _attachments[0][1], _attachments[1][1]]))
|
||||
self.assertTrue(set([_attach_1.id, _attach_2.id]).issubset(msg.attachment_ids.ids),
|
||||
'message_post: mail.message attachments duplicated')
|
||||
|
||||
# notification email attachments
|
||||
self.assertSentEmail(self.user_employee.partner_id, [self.partner_1])
|
||||
# self.assertEqual(len(self._mails), 1)
|
||||
self.assertEqual(len(self._mails[0]['attachments']), 4)
|
||||
self.assertIn(('List1', b'My first attachment', 'application/octet-stream'), self._mails[0]['attachments'])
|
||||
self.assertIn(('List2', b'My second attachment', 'application/octet-stream'), self._mails[0]['attachments'])
|
||||
self.assertIn(('Attach1', b'migration test', 'application/octet-stream'), self._mails[0]['attachments'])
|
||||
self.assertIn(('Attach2', b'migration test', 'application/octet-stream'), self._mails[0]['attachments'])
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_post_answer(self):
|
||||
with self.mock_mail_gateway():
|
||||
parent_msg = self.test_record.with_user(self.user_employee).message_post(
|
||||
body='<p>Test</p>', subject='Test Subject',
|
||||
message_type='comment', subtype_xmlid='mail.mt_comment')
|
||||
|
||||
self.assertEqual(parent_msg.partner_ids, self.env['res.partner'])
|
||||
self.assertNotSentEmail()
|
||||
|
||||
with self.assertPostNotifications([{'content': '<p>Test Answer</p>', 'notif': [{'partner': self.partner_1, 'type': 'email'}]}]):
|
||||
msg = self.test_record.with_user(self.user_employee).message_post(
|
||||
body='<p>Test Answer</p>',
|
||||
message_type='comment', subtype_xmlid='mail.mt_comment',
|
||||
partner_ids=[self.partner_1.id],
|
||||
parent_id=parent_msg.id)
|
||||
|
||||
self.assertEqual(msg.parent_id.id, parent_msg.id)
|
||||
self.assertEqual(msg.partner_ids, self.partner_1)
|
||||
self.assertEqual(parent_msg.partner_ids, self.env['res.partner'])
|
||||
|
||||
# check notification emails: references
|
||||
self.assertSentEmail(self.user_employee.partner_id, [self.partner_1], ref_content='openerp-%d-mail.test.simple' % self.test_record.id)
|
||||
# self.assertTrue(all('openerp-%d-mail.test.simple' % self.test_record.id in m['references'] for m in self._mails))
|
||||
|
||||
new_msg = self.test_record.with_user(self.user_employee).message_post(
|
||||
body='<p>Test Answer Bis</p>',
|
||||
message_type='comment', subtype_xmlid='mail.mt_comment',
|
||||
parent_id=msg.id)
|
||||
|
||||
self.assertEqual(new_msg.parent_id.id, parent_msg.id, 'message_post: flatten error')
|
||||
self.assertEqual(new_msg.partner_ids, self.env['res.partner'])
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_post_email_with_multiline_subject(self):
|
||||
_body, _body_alt, _subject = '<p>Test Body</p>', 'Test Body', '1st line\n2nd line'
|
||||
msg = self.test_record.with_user(self.user_employee).message_post(
|
||||
body=_body, subject=_subject,
|
||||
message_type='comment', subtype_xmlid='mail.mt_comment',
|
||||
partner_ids=[self.partner_1.id, self.partner_2.id]
|
||||
)
|
||||
self.assertEqual(msg.subject, '1st line 2nd line')
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_post_portal_ok(self):
|
||||
self.test_record.message_subscribe((self.partner_1 | self.user_employee.partner_id).ids)
|
||||
|
||||
with self.assertPostNotifications([{'content': '<p>Test</p>', 'notif': [
|
||||
{'partner': self.partner_employee, 'type': 'inbox'},
|
||||
{'partner': self.partner_1, 'type': 'email'}]}
|
||||
]), patch.object(MailTestSimple, 'check_access_rights', return_value=True):
|
||||
new_msg = self.test_record.with_user(self.user_portal).message_post(
|
||||
body='<p>Test</p>', subject='Subject',
|
||||
message_type='comment', subtype_xmlid='mail.mt_comment')
|
||||
|
||||
self.assertEqual(new_msg.sudo().notified_partner_ids, (self.partner_1 | self.user_employee.partner_id))
|
||||
|
||||
def test_post_portal_crash(self):
|
||||
with self.assertRaises(AccessError):
|
||||
self.test_record.with_user(self.user_portal).message_post(
|
||||
body='<p>Test</p>', subject='Subject',
|
||||
message_type='comment', subtype_xmlid='mail.mt_comment')
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.addons.mail.models.mail_thread')
|
||||
def test_post_internal(self):
|
||||
self.test_record.message_subscribe([self.user_admin.partner_id.id])
|
||||
msg = self.test_record.with_user(self.user_employee).message_post(
|
||||
body='My Body', subject='My Subject',
|
||||
message_type='comment', subtype_xmlid='mail.mt_note')
|
||||
self.assertEqual(msg.partner_ids, self.env['res.partner'])
|
||||
self.assertEqual(msg.notified_partner_ids, self.env['res.partner'])
|
||||
|
||||
self.format_and_process(
|
||||
MAIL_TEMPLATE_PLAINTEXT, self.user_admin.email, 'not_my_businesss@example.com',
|
||||
msg_id='<1198923581.41972151344608186800.JavaMail.diff1@agrolait.com>',
|
||||
extra='In-Reply-To:\r\n\t%s\n' % msg.message_id,
|
||||
target_model='mail.test.simple')
|
||||
reply = self.test_record.message_ids - msg
|
||||
self.assertTrue(reply)
|
||||
self.assertEqual(reply.subtype_id, self.env.ref('mail.mt_note'))
|
||||
self.assertEqual(reply.notified_partner_ids, self.user_employee.partner_id)
|
||||
self.assertEqual(reply.parent_id, msg)
|
||||
|
||||
def test_post_log(self):
|
||||
new_note = self.test_record.with_user(self.user_employee)._message_log(
|
||||
body='<p>Labrador</p>',
|
||||
)
|
||||
|
||||
self.assertEqual(new_note.subtype_id, self.env.ref('mail.mt_note'))
|
||||
self.assertEqual(new_note.body, '<p>Labrador</p>')
|
||||
self.assertEqual(new_note.author_id, self.user_employee.partner_id)
|
||||
self.assertEqual(new_note.email_from, formataddr((self.user_employee.name, self.user_employee.email)))
|
||||
self.assertEqual(new_note.notified_partner_ids, self.env['res.partner'])
|
||||
|
||||
def test_post_log_with_view(self):
|
||||
new_note = self.test_record.with_user(self.user_employee)._message_log_with_view(
|
||||
'test_mail.mail_template_simple_test', values={'partner': self.user_employee.partner_id}
|
||||
)
|
||||
|
||||
self.assertEqual(new_note.subtype_id, self.env.ref('mail.mt_note'))
|
||||
self.assertTrue('<p>Hello %s,</p>' % self.user_employee.name in new_note.body)
|
||||
self.assertEqual(new_note.author_id, self.user_employee.partner_id)
|
||||
self.assertEqual(new_note.email_from, formataddr((self.user_employee.name, self.user_employee.email)))
|
||||
self.assertEqual(new_note.notified_partner_ids, self.env['res.partner'])
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_post_notify(self):
|
||||
self.user_employee.write({'notification_type': 'inbox'})
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
new_notification = self.test_record.message_notify(
|
||||
subject='This should be a subject',
|
||||
new_notification = test_record.message_notify(
|
||||
body='<p>You have received a notification</p>',
|
||||
partner_ids=[self.partner_1.id, self.partner_admin.id, self.user_employee.partner_id.id],
|
||||
partner_ids=[self.partner_1.id, self.partner_admin.id, self.partner_employee_2.id],
|
||||
subject='This should be a subject',
|
||||
)
|
||||
|
||||
self.assertEqual(new_notification.subtype_id, self.env.ref('mail.mt_note'))
|
||||
self.assertEqual(new_notification.message_type, 'user_notification')
|
||||
self.assertEqual(new_notification.body, '<p>You have received a notification</p>')
|
||||
self.assertEqual(new_notification.author_id, self.env.user.partner_id)
|
||||
self.assertEqual(new_notification.email_from, formataddr((self.env.user.name, self.env.user.email)))
|
||||
self.assertEqual(new_notification.notified_partner_ids, self.partner_1 | self.user_employee.partner_id | self.partner_admin)
|
||||
self.assertMessageFields(
|
||||
new_notification,
|
||||
{'author_id': self.partner_employee,
|
||||
'body': '<p>You have received a notification</p>',
|
||||
'email_from': formataddr((self.partner_employee.name, self.partner_employee.email_normalized)),
|
||||
'message_type': 'user_notification',
|
||||
'model': test_record._name,
|
||||
'notified_partner_ids': self.partner_1 | self.partner_employee_2 | self.partner_admin,
|
||||
'res_id': test_record.id,
|
||||
'subtype_id': self.env.ref('mail.mt_note'),
|
||||
}
|
||||
)
|
||||
self.assertNotIn(new_notification, self.test_record.message_ids)
|
||||
|
||||
admin_mails = [x for x in self._mails if self.partner_admin.name in x.get('email_to')[0]]
|
||||
admin_mails = [mail for mail in self._mails if self.partner_admin.name in mail.get('email_to')[0]]
|
||||
self.assertEqual(len(admin_mails), 1, 'There should be exactly one email sent to admin')
|
||||
admin_mail = admin_mails[0].get('body')
|
||||
admin_access_link = admin_mail[admin_mail.index('model='):admin_mail.index('/>') - 1] if 'model=' in admin_mail else None
|
||||
|
||||
admin_mail_body = admin_mails[0].get('body')
|
||||
admin_access_link = admin_mail_body[admin_mail_body.index('model='):admin_mail_body.index('/>') - 1] if 'model=' in admin_mail_body else None
|
||||
|
||||
self.assertIsNotNone(admin_access_link, 'The email sent to admin should contain an access link')
|
||||
self.assertIn('model=%s' % self.test_record._name, admin_access_link, 'The access link should contain a valid model argument')
|
||||
self.assertIn('res_id=%d' % self.test_record.id, admin_access_link, 'The access link should contain a valid res_id argument')
|
||||
|
||||
partner_mails = [x for x in self._mails if self.partner_1.name in x.get('email_to')[0]]
|
||||
self.assertEqual(len(partner_mails), 1, 'There should be exactly one email sent to partner')
|
||||
partner_mail = partner_mails[0].get('body')
|
||||
self.assertNotIn('/mail/view?model=', partner_mail, 'The email sent to admin should not contain an access link')
|
||||
# todo xdo add test message_notify on thread with followers and stuff
|
||||
partner_mail_body = partner_mails[0].get('body')
|
||||
self.assertNotIn('/mail/view?model=', partner_mail_body, 'The email sent to customer should not contain an access link')
|
||||
|
||||
@users('employee')
|
||||
def test_notify_batch(self):
|
||||
""" Test notify in batch. Currently not supported. """
|
||||
test_records, _partners = self._create_records_for_batch('mail.test.simple', 10)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
test_records.message_notify(
|
||||
body='<p>Nice notification content</p>',
|
||||
partner_ids=self.partner_employee_2.ids,
|
||||
subject='Notify Subject',
|
||||
)
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_notify_from_user_id(self):
|
||||
""" Test notify coming from user_id assignment. """
|
||||
test_record = self.env['mail.test.track'].create({
|
||||
'company_id': self.env.user.company_id.id,
|
||||
'email_from': self.env.user.email_formatted,
|
||||
'name': 'Test UserId Track',
|
||||
'user_id': False,
|
||||
})
|
||||
self.flush_tracking()
|
||||
|
||||
with self.mock_mail_gateway(), self.mock_mail_app():
|
||||
test_record.write({'user_id': self.user_employee_2.id})
|
||||
self.flush_tracking()
|
||||
|
||||
self.assertEqual(len(self._new_msgs), 2, 'Should have 2 messages: tracking and assignment')
|
||||
assign_notif = self._new_msgs.filtered(lambda msg: msg.message_type == 'user_notification')
|
||||
self.assertTrue(assign_notif)
|
||||
self.assertMessageFields(
|
||||
assign_notif,
|
||||
{'author_id': self.partner_employee,
|
||||
'email_from': formataddr((self.partner_employee.name, self.partner_employee.email_normalized)),
|
||||
'model': test_record._name,
|
||||
'notified_partner_ids': self.partner_employee_2,
|
||||
'res_id': test_record.id,
|
||||
'subtype_id': self.env.ref('mail.mt_note'),
|
||||
}
|
||||
)
|
||||
self.assertIn('Dear %s' % self.partner_employee_2.name, assign_notif.body)
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_notify_from_user_id_batch(self):
|
||||
""" Test notify coming from user_id assignment. """
|
||||
test_records, _ = self._create_records_for_batch(
|
||||
'mail.test.track', 10, {
|
||||
'company_id': self.env.user.company_id.id,
|
||||
'email_from': self.env.user.email_formatted,
|
||||
'user_id': False,
|
||||
}
|
||||
)
|
||||
test_records = self.env['mail.test.track'].browse(test_records.ids)
|
||||
self.flush_tracking()
|
||||
|
||||
with self.mock_mail_gateway(), self.mock_mail_app():
|
||||
test_records.write({'user_id': self.user_employee_2.id})
|
||||
self.flush_tracking()
|
||||
|
||||
self.assertEqual(len(self._new_msgs), 20, 'Should have 20 messages: 10 tracking and 10 assignments')
|
||||
for test_record in test_records:
|
||||
assign_notif = self._new_msgs.filtered(lambda msg: msg.message_type == 'user_notification' and msg.res_id == test_record.id)
|
||||
self.assertTrue(assign_notif)
|
||||
self.assertMessageFields(
|
||||
assign_notif,
|
||||
{'author_id': self.partner_employee,
|
||||
'email_from': formataddr((self.partner_employee.name, self.partner_employee.email_normalized)),
|
||||
'model': test_record._name,
|
||||
'notified_partner_ids': self.partner_employee_2,
|
||||
'res_id': test_record.id,
|
||||
'subtype_id': self.env.ref('mail.mt_note'),
|
||||
}
|
||||
)
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_notify_thread(self):
|
||||
""" Test notify on ``mail.thread`` model, which is pushing a message to
|
||||
people without having a document. """
|
||||
with self.mock_mail_gateway():
|
||||
new_notification = self.env['mail.thread'].message_notify(
|
||||
body='<p>You have received a notification</p>',
|
||||
partner_ids=[self.partner_1.id, self.partner_admin.id, self.partner_employee_2.id],
|
||||
subject='This should be a subject',
|
||||
)
|
||||
|
||||
self.assertMessageFields(
|
||||
new_notification,
|
||||
{'author_id': self.partner_employee,
|
||||
'body': '<p>You have received a notification</p>',
|
||||
'email_from': formataddr((self.partner_employee.name, self.partner_employee.email_normalized)),
|
||||
'message_type': 'user_notification',
|
||||
'model': False,
|
||||
'res_id': False,
|
||||
'notified_partner_ids': self.partner_1 | self.partner_employee_2 | self.partner_admin,
|
||||
'subtype_id': self.env.ref('mail.mt_note'),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@tagged('mail_post')
|
||||
class TestMessagePost(TestMessagePostCommon):
|
||||
|
||||
def test_initial_values(self):
|
||||
self.assertFalse(self.test_record.message_ids)
|
||||
self.assertFalse(self.test_record.message_follower_ids)
|
||||
self.assertFalse(self.test_record.message_partner_ids)
|
||||
|
||||
@users('employee')
|
||||
def test_message_log(self):
|
||||
test_record = self.env['mail.test.simple'].browse(self.test_record.ids)
|
||||
test_record.message_subscribe(self.partner_employee_2.ids)
|
||||
|
||||
new_note = test_record._message_log(
|
||||
body='<p>Labrador</p>',
|
||||
)
|
||||
self.assertMessageFields(
|
||||
new_note,
|
||||
{'author_id': self.partner_employee,
|
||||
'body': '<p>Labrador</p>',
|
||||
'email_from': formataddr((self.partner_employee.name, self.partner_employee.email_normalized)),
|
||||
'is_internal': True,
|
||||
'message_type': 'notification',
|
||||
'model': test_record._name,
|
||||
'notified_partner_ids': self.env['res.partner'],
|
||||
'reply_to': formataddr((self.company_admin.name, '%s@%s' % (self.alias_catchall, self.alias_domain))),
|
||||
'res_id': test_record.id,
|
||||
'subtype_id': self.env.ref('mail.mt_note'),
|
||||
}
|
||||
)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
@users('employee')
|
||||
def test_message_post(self):
|
||||
self.user_employee_2.write({'notification_type': 'inbox'})
|
||||
test_record = self.env['mail.test.simple'].browse(self.test_record.ids)
|
||||
|
||||
with self.assertSinglePostNotifications(
|
||||
[{'partner': self.partner_employee_2, 'type': 'inbox'}],
|
||||
{'content': 'Body'}
|
||||
):
|
||||
new_message = test_record.message_post(
|
||||
body='Body',
|
||||
message_type='comment',
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
partner_ids=[self.partner_employee_2.id],
|
||||
)
|
||||
|
||||
self.assertMessageFields(
|
||||
new_message,
|
||||
{'author_id': self.partner_employee,
|
||||
'body': '<p>Body</p>',
|
||||
'email_from': formataddr((self.partner_employee.name, self.partner_employee.email_normalized)),
|
||||
'is_internal': False,
|
||||
'message_type': 'comment',
|
||||
'model': test_record._name,
|
||||
'notified_partner_ids': self.partner_employee_2,
|
||||
'reply_to': formataddr(("%s %s" % (self.company_admin.name, test_record.name), '%s@%s' % (self.alias_catchall, self.alias_domain))),
|
||||
'res_id': test_record.id,
|
||||
'subtype_id': self.env.ref('mail.mt_comment'),
|
||||
}
|
||||
)
|
||||
self.assertEqual(test_record.message_partner_ids, self.partner_employee)
|
||||
|
||||
test_record.message_subscribe(self.partner_1.ids)
|
||||
with self.assertSinglePostNotifications(
|
||||
[{'partner': self.partner_employee_2, 'type': 'inbox'},
|
||||
{'partner': self.partner_1, 'type': 'email'}],
|
||||
message_info={'content': 'NewBody'},
|
||||
mail_unlink_sent=True
|
||||
):
|
||||
new_message = test_record.message_post(
|
||||
body='NewBody',
|
||||
message_type='comment',
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
partner_ids=[self.partner_employee_2.id],
|
||||
)
|
||||
|
||||
self.assertMessageFields(
|
||||
new_message,
|
||||
{'notified_partner_ids': self.partner_1 + self.partner_employee_2}
|
||||
)
|
||||
# notifications emails should have been deleted
|
||||
self.assertFalse(self.env['mail.mail'].sudo().search_count([('mail_message_id', '=', new_message.id)]))
|
||||
|
||||
with self.assertSinglePostNotifications(
|
||||
[{'partner': self.partner_1, 'type': 'email'},
|
||||
{'partner': self.partner_portal, 'type': 'email'}],
|
||||
{'content': 'ToPortal'}
|
||||
):
|
||||
test_record.message_post(
|
||||
body='ToPortal',
|
||||
message_type='comment',
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
partner_ids=self.partner_portal.ids,
|
||||
)
|
||||
|
||||
@users('employee')
|
||||
def test_message_post_inactive_follower(self):
|
||||
""" Test posting with inactive followers does not notify them (e.g. odoobot) """
|
||||
test_record = self.env['mail.test.simple'].browse(self.test_record.ids)
|
||||
test_record._message_subscribe(self.user_employee_2.partner_id.ids)
|
||||
self.user_employee_2.write({'active': False})
|
||||
self.partner_employee_2.write({'active': False})
|
||||
|
||||
with self.assertPostNotifications([{'content': 'Test', 'notif': []}]):
|
||||
test_record.message_post(
|
||||
body='Test',
|
||||
message_type='comment',
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_post_post_w_template(self):
|
||||
test_record = self.env['mail.test.simple'].with_context(self._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'})
|
||||
self.user_employee.write({
|
||||
'groups_id': [(4, self.env.ref('base.group_partner_manager').id)],
|
||||
@users('employee')
|
||||
def test_message_post_keep_emails(self):
|
||||
test_record = self.env['mail.test.simple'].browse(self.test_record.ids)
|
||||
test_record.message_subscribe(partner_ids=self.partner_employee_2.ids)
|
||||
|
||||
with self.mock_mail_gateway(mail_unlink_sent=True):
|
||||
msg = test_record.message_post(
|
||||
body='Test',
|
||||
mail_auto_delete=False,
|
||||
message_type='comment',
|
||||
partner_ids=[self.partner_1.id, self.partner_2.id],
|
||||
subject='Test',
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
)
|
||||
|
||||
# notifications emails should not have been deleted: one for customers, one for user
|
||||
self.assertEqual(self.env['mail.mail'].sudo().search_count([('mail_message_id', '=', msg.id)]), 2)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
@users('employee')
|
||||
def test_message_post_w_attachments(self):
|
||||
_attachments = [
|
||||
('List1', b'My first attachment'),
|
||||
('List2', b'My second attachment'),
|
||||
]
|
||||
_attachment_records = self.env['ir.attachment'].create(
|
||||
self._generate_attachments_data(3, res_id=0, res_model='mail.compose.message')
|
||||
)
|
||||
_attachment_records[1].write({'mimetype': 'image/png'}) # to test message_main_attachment heuristic
|
||||
|
||||
test_record = self.env['mail.test.simple'].browse(self.test_record.ids)
|
||||
self.assertFalse(test_record.message_main_attachment_id)
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
msg = test_record.message_post(
|
||||
attachments=_attachments,
|
||||
attachment_ids=_attachment_records.ids,
|
||||
body='Test',
|
||||
message_type='comment',
|
||||
partner_ids=[self.partner_1.id],
|
||||
subject='Test',
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
)
|
||||
|
||||
# updated message main attachment
|
||||
self.assertEqual(test_record.message_main_attachment_id, _attachment_records[1],
|
||||
'MailThread: main attachment should be set to image/png')
|
||||
|
||||
# message attachments
|
||||
self.assertEqual(len(msg.attachment_ids), 5)
|
||||
self.assertEqual(set(msg.attachment_ids.mapped('res_model')), set([self.test_record._name]))
|
||||
self.assertEqual(set(msg.attachment_ids.mapped('res_id')), set([self.test_record.id]))
|
||||
self.assertEqual(set(base64.b64decode(x) for x in msg.attachment_ids.mapped('datas')),
|
||||
set([b'AttContent_00', b'AttContent_01', b'AttContent_02', _attachments[0][1], _attachments[1][1]]))
|
||||
self.assertTrue(set(_attachment_records.ids).issubset(msg.attachment_ids.ids),
|
||||
'message_post: mail.message attachments duplicated')
|
||||
|
||||
# notification email attachments
|
||||
self.assertEqual(len(self._mails), 1)
|
||||
self.assertSentEmail(
|
||||
self.user_employee.partner_id, [self.partner_1],
|
||||
attachments=[('List1', b'My first attachment', 'application/octet-stream'),
|
||||
('List2', b'My second attachment', 'application/octet-stream'),
|
||||
('AttFileName_00.txt', b'AttContent_00', 'text/plain'),
|
||||
('AttFileName_01.txt', b'AttContent_01', 'image/png'),
|
||||
('AttFileName_02.txt', b'AttContent_02', 'text/plain'),
|
||||
]
|
||||
)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_multiline_subject(self):
|
||||
with self.mock_mail_gateway():
|
||||
msg = self.test_record.with_user(self.user_employee).message_post(
|
||||
body='<p>Test Body</p>',
|
||||
partner_ids=[self.partner_1.id, self.partner_2.id],
|
||||
subject='1st line\n2nd line',
|
||||
)
|
||||
self.assertEqual(msg.subject, '1st line 2nd line')
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_portal_acls(self):
|
||||
self.test_record.message_subscribe((self.partner_1 | self.user_employee.partner_id).ids)
|
||||
|
||||
with self.assertPostNotifications(
|
||||
[{'content': '<p>Test</p>', 'notif': [
|
||||
{'partner': self.partner_employee, 'type': 'inbox'},
|
||||
{'partner': self.partner_1, 'type': 'email'}]}
|
||||
]
|
||||
), patch.object(MailTestSimple, 'check_access_rights', return_value=True):
|
||||
new_msg = self.test_record.with_user(self.user_portal).message_post(
|
||||
body='<p>Test</p>',
|
||||
message_type='comment',
|
||||
subject='Subject',
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
)
|
||||
self.assertEqual(new_msg.sudo().notified_partner_ids, (self.partner_1 | self.user_employee.partner_id))
|
||||
|
||||
with self.assertRaises(AccessError):
|
||||
self.test_record.with_user(self.user_portal).message_post(
|
||||
body='<p>Test</p>',
|
||||
message_type='comment',
|
||||
subject='Subject',
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
@users('employee')
|
||||
def test_post_answer(self):
|
||||
test_record = self.env['mail.test.simple'].browse(self.test_record.ids)
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
parent_msg = test_record.message_post(
|
||||
body='<p>Test</p>',
|
||||
message_type='comment',
|
||||
subject='Test Subject',
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
)
|
||||
self.assertFalse(parent_msg.partner_ids)
|
||||
self.assertNotSentEmail()
|
||||
|
||||
with self.assertPostNotifications(
|
||||
[{'content': '<p>Test Answer</p>', 'notif': [{'partner': self.partner_1, 'type': 'email'}]}]
|
||||
):
|
||||
msg = test_record.message_post(
|
||||
body='<p>Test Answer</p>',
|
||||
message_type='comment',
|
||||
parent_id=parent_msg.id,
|
||||
partner_ids=[self.partner_1.id],
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
)
|
||||
self.assertEqual(msg.parent_id, parent_msg)
|
||||
self.assertEqual(msg.partner_ids, self.partner_1)
|
||||
self.assertFalse(parent_msg.partner_ids)
|
||||
|
||||
# check notification emails: references
|
||||
self.assertSentEmail(
|
||||
self.user_employee.partner_id, [self.partner_1],
|
||||
ref_content='openerp-%d-mail.test.simple' % self.test_record.id
|
||||
)
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
new_msg = test_record.message_post(
|
||||
body='<p>Test Answer Bis</p>',
|
||||
message_type='comment',
|
||||
parent_id=msg.id,
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
)
|
||||
self.assertEqual(new_msg.parent_id, parent_msg, 'message_post: flatten error')
|
||||
self.assertFalse(new_msg.partner_ids)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.addons.mail.models.mail_thread')
|
||||
@users('employee')
|
||||
def test_post_internal(self):
|
||||
test_record = self.env['mail.test.simple'].browse(self.test_record.ids)
|
||||
|
||||
test_record.message_subscribe([self.user_admin.partner_id.id])
|
||||
with self.mock_mail_gateway():
|
||||
msg = test_record.message_post(
|
||||
body='My Body',
|
||||
message_type='comment',
|
||||
subject='My Subject',
|
||||
subtype_xmlid='mail.mt_note',
|
||||
)
|
||||
self.assertFalse(msg.is_internal,
|
||||
'Notes are not "internal" but replies will be. Subtype being internal should be sufficient from ACLs point of view.')
|
||||
self.assertFalse(msg.partner_ids)
|
||||
self.assertFalse(msg.notified_partner_ids)
|
||||
|
||||
self.format_and_process(
|
||||
MAIL_TEMPLATE_PLAINTEXT, self.user_admin.email, 'not_my_businesss@example.com',
|
||||
msg_id='<1198923581.41972151344608186800.JavaMail.diff1@agrolait.example.com>',
|
||||
extra='In-Reply-To:\r\n\t%s\n' % msg.message_id,
|
||||
target_model='mail.test.simple')
|
||||
reply = test_record.message_ids - msg
|
||||
self.assertTrue(reply)
|
||||
self.assertTrue(reply.is_internal)
|
||||
self.assertEqual(reply.notified_partner_ids, self.user_employee.partner_id)
|
||||
self.assertEqual(reply.parent_id, msg)
|
||||
self.assertEqual(reply.subtype_id, self.env.ref('mail.mt_note'))
|
||||
|
||||
|
||||
@tagged('mail_post')
|
||||
class TestMessagePostHelpers(TestMessagePostCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMessagePostHelpers, cls).setUpClass()
|
||||
# ensure employee can create partners, necessary for templates
|
||||
cls.user_employee.write({
|
||||
'groups_id': [(4, cls.env.ref('base.group_partner_manager').id)],
|
||||
})
|
||||
_attachments = [{
|
||||
'name': 'first.txt',
|
||||
'datas': base64.b64encode(b'My first attachment'),
|
||||
'res_model': 'res.partner',
|
||||
'res_id': self.user_admin.partner_id.id
|
||||
}, {
|
||||
'name': 'second.txt',
|
||||
'datas': base64.b64encode(b'My second attachment'),
|
||||
'res_model': 'res.partner',
|
||||
'res_id': self.user_admin.partner_id.id
|
||||
}]
|
||||
|
||||
@users('employee')
|
||||
def test_message_log_with_view(self):
|
||||
test_record = self.env['mail.test.simple'].browse(self.test_record.ids)
|
||||
new_note = test_record._message_log_with_view(
|
||||
'test_mail.mail_template_simple_test',
|
||||
values={'partner': self.user_employee.partner_id}
|
||||
)
|
||||
self.assertMessageFields(
|
||||
new_note,
|
||||
{'author_id': self.partner_employee,
|
||||
'body': '<p>Hello %s,</p>' % self.user_employee.name,
|
||||
'email_from': formataddr((self.partner_employee.name, self.partner_employee.email_normalized)),
|
||||
'is_internal': True,
|
||||
'message_type': 'notification',
|
||||
'model': test_record._name,
|
||||
'notified_partner_ids': self.env['res.partner'],
|
||||
'reply_to': formataddr((self.company_admin.name, '%s@%s' % (self.alias_catchall, self.alias_domain))),
|
||||
'res_id': test_record.id,
|
||||
'subtype_id': self.env.ref('mail.mt_note'),
|
||||
}
|
||||
)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_message_post_w_template(self):
|
||||
test_record = self.env['mail.test.simple'].with_context(self._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'})
|
||||
|
||||
_attachments = self._generate_attachments_data(count=2, res_id=0, res_model='mail.template')
|
||||
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])],
|
||||
template = self._create_template('mail.test.simple', {
|
||||
'attachment_ids': [(0, 0, attach_vals) for attach_vals in _attachments],
|
||||
'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,
|
||||
})
|
||||
template.attachment_ids.write({'res_id': template.id})
|
||||
|
||||
# admin should receive emails
|
||||
self.user_admin.write({'notification_type': 'email'})
|
||||
# Force the attachments of the template to be in the natural order.
|
||||
@@ -534,25 +766,35 @@ class TestMessagePost(TestMailCommon, TestRecipients):
|
||||
[r],
|
||||
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')])
|
||||
attachments=[
|
||||
('AttFileName_00.txt', b'AttContent_00', 'text/plain'),
|
||||
('AttFileName_01.txt', b'AttContent_01', 'text/plain'),
|
||||
]
|
||||
)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_post_post_w_template_mass_mode(self):
|
||||
def test_message_post_w_template_mass_mode(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)],
|
||||
})
|
||||
|
||||
self._create_template('mail.test.simple', {
|
||||
'partner_to': '%s,%s' % (self.partner_2.id, self.user_admin.partner_id.id),
|
||||
'email_to': 'test@example.com',
|
||||
'email_cc': self.partner_1.email,
|
||||
_attachments = self._generate_attachments_data(count=2, res_id=0, res_model='mail.template')
|
||||
template = self._create_template('mail.test.simple', {
|
||||
'attachment_ids': [(0, 0, attach_vals) for attach_vals in _attachments],
|
||||
# After the HTML sanitizer, it will become "<p>Body for: <t t-out="object.name" /><a href="">link</a></p>"
|
||||
'body_html': 'Body for: <t t-out="object.name" /><script>test</script><a href="javascript:alert(1)">link</a>',
|
||||
'email_to': 'test@example.com',
|
||||
'email_cc': self.partner_1.email,
|
||||
'partner_to': '%s,%s' % (self.partner_2.id, self.user_admin.partner_id.id),
|
||||
})
|
||||
template.attachment_ids.write({'res_id': template.id})
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
test_record.with_user(self.user_employee).message_post_with_template(self.email_template.id, composition_mode='mass_mail')
|
||||
test_record.with_user(self.user_employee).message_post_with_template(
|
||||
template.id,
|
||||
composition_mode='mass_mail'
|
||||
)
|
||||
|
||||
new_partner = self.env['res.partner'].search([('email', '=', 'test@example.com')])
|
||||
|
||||
@@ -561,21 +803,15 @@ class TestMessagePost(TestMailCommon, TestRecipients):
|
||||
[new_partner],
|
||||
subject='About %s' % test_record.name,
|
||||
body_content=test_record.name,
|
||||
attachments=[])
|
||||
attachments=[
|
||||
('AttFileName_00.txt', b'AttContent_00', 'text/plain'),
|
||||
('AttFileName_01.txt', b'AttContent_01', 'text/plain'),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@tagged('mail_post', 'post_install', '-at_install')
|
||||
class TestMessagePostGlobal(TestMailCommon, TestRecipients):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMessagePostGlobal, cls).setUpClass()
|
||||
cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({
|
||||
'email_from': 'ignasse@example.com',
|
||||
'name': 'Test',
|
||||
})
|
||||
cls._reset_mail_context(cls.test_record)
|
||||
cls.user_admin.write({'notification_type': 'email'})
|
||||
class TestMessagePostGlobal(TestMessagePostCommon):
|
||||
|
||||
@users('employee')
|
||||
def test_message_post_return(self):
|
||||
@@ -586,8 +822,7 @@ class TestMessagePostGlobal(TestMailCommon, TestRecipients):
|
||||
message_id = call_kw(self.env['mail.test.simple'],
|
||||
'message_post',
|
||||
[test_record.id],
|
||||
{'body': 'test'}
|
||||
)
|
||||
{'body': 'test'})
|
||||
self.assertTrue(isinstance(message_id, int))
|
||||
|
||||
|
||||
@@ -631,6 +866,7 @@ class TestMessagePostLang(TestMailCommon, TestRecipients):
|
||||
cls.partner_2.write({'lang': 'es_ES'})
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_composer_lang_template(self):
|
||||
test_records = self.test_records.with_user(self.env.user)
|
||||
test_template = self.test_template.with_user(self.env.user)
|
||||
@@ -659,6 +895,7 @@ class TestMessagePostLang(TestMailCommon, TestRecipients):
|
||||
self.assertEqual('EnglishSubject for %s' % record.name, customer_email['subject'], 'Fixme: this should be translated')
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_layout_email_lang_context(self):
|
||||
test_records = self.test_records.with_user(self.env.user).with_context(lang='es_ES')
|
||||
test_records[1].message_subscribe(self.partner_2.ids)
|
||||
@@ -687,6 +924,7 @@ class TestMessagePostLang(TestMailCommon, TestRecipients):
|
||||
self.assertIn('Hello', body, 'Body of posted message should be present')
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_layout_email_lang_template(self):
|
||||
test_records = self.test_records.with_user(self.env.user)
|
||||
test_template = self.test_template.with_user(self.env.user)
|
||||
|
||||
@@ -1,70 +1,41 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import base64
|
||||
|
||||
from odoo.addons.base.tests.common import TransactionCaseWithUserDemo
|
||||
from odoo.tests.common import users, warmup
|
||||
from odoo.addons.mail.tests.common import MailCommon
|
||||
from odoo.tests.common import users, warmup, Form
|
||||
from odoo.tests import tagged
|
||||
from odoo.tools import mute_logger, formataddr
|
||||
|
||||
|
||||
@tagged('mail_performance')
|
||||
class BaseMailPerformance(TransactionCaseWithUserDemo):
|
||||
class BaseMailPerformance(MailCommon, TransactionCaseWithUserDemo):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(BaseMailPerformance, cls).setUpClass()
|
||||
cls._quick_create_ctx = {
|
||||
'no_reset_password': True,
|
||||
'mail_create_nolog': True,
|
||||
'mail_create_nosubscribe': True,
|
||||
'mail_notrack': True,
|
||||
'mail_channel_nosubscribe': True,
|
||||
}
|
||||
|
||||
cls.user_employee = cls.env['res.users'].with_context(cls._quick_create_ctx).create({
|
||||
'country_id': cls.env.ref('base.be').id,
|
||||
'email': 'e.e@example.com',
|
||||
'groups_id': [(6, 0, [cls.env.ref('base.group_user').id, cls.env.ref('base.group_partner_manager').id])],
|
||||
'login': 'employee',
|
||||
'name': 'Ernest Employee',
|
||||
'notification_type': 'inbox',
|
||||
'signature': '--\nErnest',
|
||||
})
|
||||
cls.admin = cls.env.user
|
||||
cls.admin.write({
|
||||
'country_id': cls.env.ref('base.be').id,
|
||||
})
|
||||
# creating partners is required notably witn template usage
|
||||
cls.user_employee.write({'groups_id': [(4, cls.env.ref('base.group_partner_manager').id)]})
|
||||
|
||||
cls.customer = cls.env['res.partner'].with_context(cls._quick_create_ctx).create({
|
||||
cls.customer = cls.env['res.partner'].with_context(cls._test_context).create({
|
||||
'country_id': cls.env.ref('base.be').id,
|
||||
'email': 'customer.test@example.com',
|
||||
'name': 'Test Customer',
|
||||
'mobile': '0456123456',
|
||||
})
|
||||
|
||||
cls.test_attachments_vals = cls._generate_attachments_data(
|
||||
cls, 3, res_model='mail.compose.message', res_id=0
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
super(BaseMailPerformance, self).setUp()
|
||||
# patch registry to simulate a ready environment
|
||||
self.patch(self.env.registry, 'ready', True)
|
||||
self._flush_tracking()
|
||||
|
||||
def _init_mail_gateway(self):
|
||||
# setup mail gateway
|
||||
self.alias_domain = 'example.com'
|
||||
self.alias_catchall = 'catchall.test'
|
||||
self.alias_bounce = 'bounce.test'
|
||||
self.default_from = 'notifications'
|
||||
self.env['ir.config_parameter'].set_param('mail.bounce.alias', self.alias_bounce)
|
||||
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)
|
||||
self.env['ir.config_parameter'].set_param('mail.default.from', self.default_from)
|
||||
|
||||
def _flush_tracking(self):
|
||||
""" Force the creation of tracking values notably, and ensure tests are
|
||||
reproducible. """
|
||||
self.env['base'].flush()
|
||||
self.cr.flush()
|
||||
self.flush_tracking()
|
||||
|
||||
|
||||
@tagged('mail_performance')
|
||||
@@ -113,8 +84,6 @@ class TestBaseMailPerformance(BaseMailPerformance):
|
||||
}
|
||||
])
|
||||
|
||||
self._init_mail_gateway()
|
||||
|
||||
@users('__system__', 'demo')
|
||||
@warmup
|
||||
def test_read_mail(self):
|
||||
@@ -215,7 +184,7 @@ class TestMailAPIPerformance(BaseMailPerformance):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMailAPIPerformance, self).setUp()
|
||||
self.user_test = self.env['res.users'].with_context(self._quick_create_ctx).create({
|
||||
self.user_test = self.env['res.users'].with_context(self._test_context).create({
|
||||
'name': 'Paulette Testouille',
|
||||
'login': 'paul',
|
||||
'email': 'user.test.paulette@example.com',
|
||||
@@ -223,13 +192,11 @@ class TestMailAPIPerformance(BaseMailPerformance):
|
||||
'groups_id': [(6, 0, [self.env.ref('base.group_user').id])],
|
||||
})
|
||||
|
||||
self._init_mail_gateway()
|
||||
|
||||
# automatically follow activities, for backward compatibility concerning query count
|
||||
self.env.ref('mail.mt_activities').write({'default': True})
|
||||
|
||||
def _create_test_records(self):
|
||||
self.test_record_full = self.env['mail.test.ticket'].with_context(self._quick_create_ctx).create({
|
||||
self.test_record_full = self.env['mail.test.ticket'].with_context(self._test_context).create({
|
||||
'name': 'TestRecord',
|
||||
'customer_id': self.customer.id,
|
||||
'user_id': self.user_test.id,
|
||||
@@ -243,6 +210,10 @@ class TestMailAPIPerformance(BaseMailPerformance):
|
||||
'email_from': '{{ object.user_id.email_formatted }}',
|
||||
'partner_to': '{{ object.customer_id.id }}',
|
||||
'email_to': '{{ ("%s Customer <%s>" % (object.name, object.email_from)) }}',
|
||||
'attachment_ids': [
|
||||
(0, 0, dict(attachment, res_model='mail.template'))
|
||||
for attachment in self.test_attachments_vals
|
||||
],
|
||||
})
|
||||
|
||||
@users('__system__', 'employee')
|
||||
@@ -268,9 +239,9 @@ class TestMailAPIPerformance(BaseMailPerformance):
|
||||
'res_id': record.id,
|
||||
'activity_type_id': self.env.ref('mail.mail_activity_data_todo').id,
|
||||
})
|
||||
#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_feedback
|
||||
category = activity.activity_type_id.category
|
||||
# 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_feedback
|
||||
_category = activity.activity_type_id.category
|
||||
|
||||
with self.assertQueryCount(__system__=17, employee=19):
|
||||
activity.action_feedback(feedback='Zizisse Done !')
|
||||
@@ -283,9 +254,9 @@ class TestMailAPIPerformance(BaseMailPerformance):
|
||||
|
||||
with self.assertQueryCount(__system__=8, employee=8):
|
||||
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
|
||||
category = activity.activity_type_id.category
|
||||
# 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
|
||||
_category = activity.activity_type_id.category
|
||||
|
||||
record.write({'name': 'Dupe write'})
|
||||
|
||||
@@ -296,7 +267,38 @@ class TestMailAPIPerformance(BaseMailPerformance):
|
||||
|
||||
@users('__system__', 'employee')
|
||||
@warmup
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_adv_activity_mixin_w_attachments(self):
|
||||
record = self.env['mail.test.activity'].create({'name': 'Test'})
|
||||
|
||||
attachments = self.env['ir.attachment'].create([
|
||||
dict(values,
|
||||
res_model='mail.activity',
|
||||
res_id=0)
|
||||
for values in self.test_attachments_vals
|
||||
])
|
||||
|
||||
with self.assertQueryCount(__system__=8, employee=8):
|
||||
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
|
||||
_category = activity.activity_type_id.category
|
||||
|
||||
record.write({'name': 'Dupe write'})
|
||||
|
||||
with self.assertQueryCount(__system__=20, employee=24):
|
||||
record.action_close('Dupe feedback', attachment_ids=attachments.ids)
|
||||
|
||||
# notifications
|
||||
message = record.message_ids[0]
|
||||
self.assertEqual(
|
||||
set(message.attachment_ids.mapped('name')),
|
||||
set(['AttFileName_00.txt', 'AttFileName_01.txt', 'AttFileName_02.txt'])
|
||||
)
|
||||
|
||||
@users('__system__', 'employee')
|
||||
@warmup
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink', 'odoo.tests')
|
||||
def test_mail_composer(self):
|
||||
self._create_test_records()
|
||||
test_record = self.env['mail.test.ticket'].browse(self.test_record_full.id)
|
||||
@@ -311,12 +313,64 @@ class TestMailAPIPerformance(BaseMailPerformance):
|
||||
'partner_ids': [(4, customer_id)],
|
||||
})
|
||||
|
||||
with self.assertQueryCount(__system__=32, employee=38):
|
||||
with self.assertQueryCount(__system__=33, employee=39):
|
||||
composer._action_send_mail()
|
||||
|
||||
@users('__system__', 'employee')
|
||||
@warmup
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink', 'odoo.tests')
|
||||
def test_mail_composer_attachments(self):
|
||||
self._create_test_records()
|
||||
test_record = self.env['mail.test.ticket'].browse(self.test_record_full.id)
|
||||
customer = self.env['res.partner'].browse(self.customer.ids)
|
||||
attachments = self.env['ir.attachment'].with_user(self.env.user).create(self.test_attachments_vals)
|
||||
with self.assertQueryCount(__system__=3, employee=3):
|
||||
composer = self.env['mail.compose.message'].with_context({
|
||||
'default_composition_mode': 'comment',
|
||||
'default_model': test_record._name,
|
||||
'default_res_id': test_record.id,
|
||||
}).create({
|
||||
'attachment_ids': attachments.ids,
|
||||
'body': '<p>Test Body</p>',
|
||||
'partner_ids': [(4, customer.id)],
|
||||
})
|
||||
|
||||
with self.assertQueryCount(__system__=36, employee=44):
|
||||
composer._action_send_mail()
|
||||
|
||||
@users('__system__', 'employee')
|
||||
@warmup
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink', 'odoo.tests')
|
||||
def test_mail_composer_form_attachments(self):
|
||||
self._create_test_records()
|
||||
test_record = self.env['mail.test.ticket'].browse(self.test_record_full.id)
|
||||
customer = self.env['res.partner'].browse(self.customer.ids)
|
||||
attachments = self.env['ir.attachment'].with_user(self.env.user).create(self.test_attachments_vals)
|
||||
with self.assertQueryCount(__system__=15, employee=15):
|
||||
composer_form = Form(
|
||||
self.env['mail.compose.message'].with_context({
|
||||
'default_composition_mode': 'comment',
|
||||
'default_model': test_record._name,
|
||||
'default_res_id': test_record.id,
|
||||
})
|
||||
)
|
||||
composer_form.body = '<p>Test Body</p>'
|
||||
composer_form.partner_ids.add(customer)
|
||||
for attachment in attachments:
|
||||
composer_form.attachment_ids.add(attachment)
|
||||
composer = composer_form.save()
|
||||
|
||||
with self.assertQueryCount(__system__=44, employee=52):
|
||||
composer._action_send_mail()
|
||||
|
||||
# notifications
|
||||
message = test_record.message_ids[0]
|
||||
self.assertEqual(message.attachment_ids, attachments)
|
||||
self.assertEqual(message.notified_partner_ids, customer + self.user_test.partner_id)
|
||||
|
||||
@users('__system__', 'employee')
|
||||
@warmup
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink', 'odoo.tests')
|
||||
def test_mail_composer_nodelete(self):
|
||||
self._create_test_records()
|
||||
test_record = self.env['mail.test.ticket'].browse(self.test_record_full.id)
|
||||
@@ -332,16 +386,19 @@ class TestMailAPIPerformance(BaseMailPerformance):
|
||||
'partner_ids': [(4, customer_id)],
|
||||
})
|
||||
|
||||
with self.assertQueryCount(__system__=25, employee=31):
|
||||
with self.assertQueryCount(__system__=26, employee=32):
|
||||
composer._action_send_mail()
|
||||
|
||||
@users('__system__', 'employee')
|
||||
@warmup
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink', 'odoo.tests')
|
||||
def test_mail_composer_w_template(self):
|
||||
self._create_test_records()
|
||||
self.test_template_full.write({'attachment_ids': [(5, 0)]})
|
||||
|
||||
test_record = self.env['mail.test.ticket'].browse(self.test_record_full.id)
|
||||
test_template = self.env['mail.template'].browse(self.test_template_full.id)
|
||||
|
||||
with self.assertQueryCount(__system__=11, employee=12):
|
||||
composer = self.env['mail.compose.message'].with_context({
|
||||
'default_composition_mode': 'comment',
|
||||
@@ -351,19 +408,121 @@ class TestMailAPIPerformance(BaseMailPerformance):
|
||||
}).create({})
|
||||
composer._onchange_template_id_wrapper()
|
||||
|
||||
with self.assertQueryCount(__system__=32, employee=38):
|
||||
with self.assertQueryCount(__system__=33, employee=39):
|
||||
composer._action_send_mail()
|
||||
|
||||
# notifications
|
||||
message = test_record.message_ids[0]
|
||||
self.assertFalse(message.attachment_ids)
|
||||
|
||||
# remove created partner to ensure tests are the same each run
|
||||
self.env['res.partner'].sudo().search([('email', '=', 'nopartner.test@example.com')]).unlink()
|
||||
|
||||
@users('__system__', 'employee')
|
||||
@warmup
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink', 'odoo.tests')
|
||||
def test_mail_composer_w_template_attachments(self):
|
||||
self._create_test_records()
|
||||
|
||||
test_record = self.env['mail.test.ticket'].browse(self.test_record_full.id)
|
||||
test_template = self.env['mail.template'].browse(self.test_template_full.id)
|
||||
with self.assertQueryCount(__system__=12, employee=13):
|
||||
composer = self.env['mail.compose.message'].with_context({
|
||||
'default_composition_mode': 'comment',
|
||||
'default_model': test_record._name,
|
||||
'default_res_id': test_record.id,
|
||||
'default_template_id': test_template.id,
|
||||
}).create({})
|
||||
composer._onchange_template_id_wrapper()
|
||||
|
||||
with self.assertQueryCount(__system__=41, employee=52):
|
||||
composer._action_send_mail()
|
||||
|
||||
# notifications
|
||||
message = test_record.message_ids[0]
|
||||
self.assertEqual(
|
||||
set(message.attachment_ids.mapped('name')),
|
||||
set(['AttFileName_00.txt', 'AttFileName_01.txt', 'AttFileName_02.txt'])
|
||||
)
|
||||
|
||||
# remove created partner to ensure tests are the same each run
|
||||
self.env['res.partner'].sudo().search([('email', '=', 'nopartner.test@example.com')]).unlink()
|
||||
|
||||
@users('__system__', 'employee')
|
||||
@warmup
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink', 'odoo.tests')
|
||||
def test_mail_composer_w_template_form(self):
|
||||
self._create_test_records()
|
||||
self.test_template_full.write({'attachment_ids': [(5, 0)]})
|
||||
|
||||
test_record = self.env['mail.test.ticket'].browse(self.test_record_full.id)
|
||||
test_template = self.env['mail.template'].browse(self.test_template_full.id)
|
||||
customer = self.env['res.partner'].browse(self.customer.ids)
|
||||
with self.assertQueryCount(__system__=33, employee=33):
|
||||
composer_form = Form(
|
||||
self.env['mail.compose.message'].with_context({
|
||||
'default_composition_mode': 'comment',
|
||||
'default_model': test_record._name,
|
||||
'default_res_id': test_record.id,
|
||||
'default_template_id': test_template.id,
|
||||
})
|
||||
)
|
||||
composer = composer_form.save()
|
||||
|
||||
with self.assertQueryCount(__system__=41, employee=47):
|
||||
composer._action_send_mail()
|
||||
|
||||
# notifications
|
||||
new_partner = self.env['res.partner'].sudo().search([('email', '=', 'nopartner.test@example.com')])
|
||||
message = test_record.message_ids[0]
|
||||
self.assertFalse(message.attachment_ids)
|
||||
self.assertEqual(message.notified_partner_ids, customer + self.user_test.partner_id + new_partner)
|
||||
|
||||
# remove created partner to ensure tests are the same each run
|
||||
new_partner.unlink()
|
||||
|
||||
@users('__system__', 'employee')
|
||||
@warmup
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink', 'odoo.tests')
|
||||
def test_mail_composer_w_template_form_attachments(self):
|
||||
self._create_test_records()
|
||||
|
||||
test_record = self.env['mail.test.ticket'].browse(self.test_record_full.id)
|
||||
test_template = self.env['mail.template'].browse(self.test_template_full.id)
|
||||
customer = self.env['res.partner'].browse(self.customer.ids)
|
||||
with self.assertQueryCount(__system__=34, employee=34):
|
||||
composer_form = Form(
|
||||
self.env['mail.compose.message'].with_context({
|
||||
'default_composition_mode': 'comment',
|
||||
'default_model': test_record._name,
|
||||
'default_res_id': test_record.id,
|
||||
'default_template_id': test_template.id,
|
||||
})
|
||||
)
|
||||
composer = composer_form.save()
|
||||
|
||||
with self.assertQueryCount(__system__=53, employee=70):
|
||||
composer._action_send_mail()
|
||||
|
||||
# notifications
|
||||
new_partner = self.env['res.partner'].sudo().search([('email', '=', 'nopartner.test@example.com')])
|
||||
message = test_record.message_ids[0]
|
||||
self.assertEqual(
|
||||
set(message.attachment_ids.mapped('name')),
|
||||
set(['AttFileName_00.txt', 'AttFileName_01.txt', 'AttFileName_02.txt'])
|
||||
)
|
||||
self.assertEqual(message.notified_partner_ids, customer + self.user_test.partner_id + new_partner)
|
||||
|
||||
# remove created partner to ensure tests are the same each run
|
||||
new_partner.unlink()
|
||||
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
@users('__system__', 'employee')
|
||||
@warmup
|
||||
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__=38, employee=39):
|
||||
with self.assertQueryCount(__system__=39, employee=40):
|
||||
record.write({
|
||||
'user_id': self.user_test.id,
|
||||
})
|
||||
@@ -416,7 +575,7 @@ class TestMailAPIPerformance(BaseMailPerformance):
|
||||
def test_message_post_one_email_notification(self):
|
||||
record = self.env['mail.test.simple'].create({'name': 'Test'})
|
||||
|
||||
with self.assertQueryCount(__system__=29, employee=32):
|
||||
with self.assertQueryCount(__system__=30, employee=33):
|
||||
record.message_post(
|
||||
body='<p>Test Post Performances with an email ping</p>',
|
||||
partner_ids=self.customer.ids,
|
||||
@@ -511,7 +670,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMailComplexPerformance, self).setUp()
|
||||
self.user_portal = self.env['res.users'].with_context(self._quick_create_ctx).create({
|
||||
self.user_portal = self.env['res.users'].with_context(self._test_context).create({
|
||||
'name': 'Olivia Portal',
|
||||
'login': 'port',
|
||||
'email': 'p.p@example.com',
|
||||
@@ -525,16 +684,14 @@ class TestMailComplexPerformance(BaseMailPerformance):
|
||||
'customer_id': self.customer.id,
|
||||
'alias_name': 'test-alias',
|
||||
})
|
||||
Partners = self.env['res.partner'].with_context(self._quick_create_ctx)
|
||||
Partners = self.env['res.partner'].with_context(self._test_context)
|
||||
self.partners = self.env['res.partner']
|
||||
for x in range(0, 10):
|
||||
self.partners |= Partners.create({'name': 'Test %s' % x, 'email': 'test%s@example.com' % x})
|
||||
self.container.message_subscribe(self.partners.ids, subtype_ids=[
|
||||
self.env.ref('mail.mt_comment').id,
|
||||
self.env.ref('test_mail.st_mail_test_container_child_full').id]
|
||||
)
|
||||
|
||||
self._init_mail_gateway()
|
||||
self.env.ref('test_mail.st_mail_test_container_child_full').id
|
||||
])
|
||||
|
||||
# `test_complex_mail_mail_send`
|
||||
self.container.flush()
|
||||
@@ -557,11 +714,13 @@ class TestMailComplexPerformance(BaseMailPerformance):
|
||||
'recipient_ids': [(4, pid) for pid in self.partners.ids],
|
||||
})
|
||||
mail_ids = mail.ids
|
||||
with self.assertQueryCount(__system__=8, employee=8):
|
||||
with self.assertQueryCount(__system__=9, employee=9):
|
||||
self.env['mail.mail'].sudo().browse(mail_ids).send()
|
||||
|
||||
self.assertEqual(mail.body_html, '<p>Test</p>')
|
||||
self.assertEqual(mail.reply_to, formataddr(('%s %s' % (self.env.company.name, self.container.name), 'test-alias@example.com')))
|
||||
self.assertEqual(mail.reply_to, formataddr(
|
||||
('%s %s' % (self.env.company.name, self.container.name), 'test-alias@%s' % self.alias_domain)
|
||||
))
|
||||
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
@users('__system__', 'employee')
|
||||
@@ -570,7 +729,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
|
||||
self.container.message_subscribe(self.user_portal.partner_id.ids)
|
||||
record = self.container.with_user(self.env.user)
|
||||
|
||||
with self.assertQueryCount(__system__=53, employee=54): # about 20 (19?) queries per additional customer group
|
||||
with self.assertQueryCount(__system__=54, employee=55): # about 20 (19?) queries per additional customer group
|
||||
record.message_post(
|
||||
body='<p>Test Post Performances</p>',
|
||||
message_type='comment',
|
||||
@@ -587,7 +746,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
|
||||
record = self.container.with_user(self.env.user)
|
||||
template_id = self.env.ref('test_mail.mail_test_container_tpl').id
|
||||
|
||||
with self.assertQueryCount(__system__=61, employee=62): # about 20 (19 ?) queries per additional customer group
|
||||
with self.assertQueryCount(__system__=62, employee=63): # about 20 (19 ?) queries per additional customer group
|
||||
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)
|
||||
@@ -650,7 +809,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
|
||||
})
|
||||
rec1 = rec.with_context(active_test=False) # to see inactive records
|
||||
self.assertEqual(rec1.message_partner_ids, self.partners | self.env.user.partner_id)
|
||||
with self.assertQueryCount(__system__=38, employee=39):
|
||||
with self.assertQueryCount(__system__=39, employee=40):
|
||||
rec.write({'user_id': self.user_portal.id})
|
||||
self.assertEqual(rec1.message_partner_ids, self.partners | self.env.user.partner_id | self.user_portal.partner_id)
|
||||
# write tracking message
|
||||
@@ -670,7 +829,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
|
||||
customer_id = self.customer.id
|
||||
user_id = self.user_portal.id
|
||||
|
||||
with self.assertQueryCount(__system__=89, employee=90):
|
||||
with self.assertQueryCount(__system__=91, employee=92):
|
||||
rec = self.env['mail.test.ticket'].create({
|
||||
'name': 'Test',
|
||||
'container_id': container_id,
|
||||
@@ -699,7 +858,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
|
||||
rec1 = rec.with_context(active_test=False) # to see inactive records
|
||||
self.assertEqual(rec1.message_partner_ids, self.user_portal.partner_id | self.env.user.partner_id)
|
||||
self.assertEqual(len(rec1.message_ids), 1)
|
||||
with self.assertQueryCount(__system__=58, employee=58):
|
||||
with self.assertQueryCount(__system__=59, employee=59):
|
||||
rec.write({
|
||||
'name': 'Test2',
|
||||
'container_id': self.container.id,
|
||||
@@ -736,7 +895,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
|
||||
rec1 = rec.with_context(active_test=False) # to see inactive records
|
||||
self.assertEqual(rec1.message_partner_ids, self.user_portal.partner_id | self.env.user.partner_id)
|
||||
|
||||
with self.assertQueryCount(__system__=65, employee=65):
|
||||
with self.assertQueryCount(__system__=66, employee=66):
|
||||
rec.write({
|
||||
'name': 'Test2',
|
||||
'container_id': container_id,
|
||||
@@ -769,7 +928,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
|
||||
rec1 = rec.with_context(active_test=False) # to see inactive records
|
||||
self.assertEqual(rec1.message_partner_ids, self.partners | self.env.user.partner_id | self.user_portal.partner_id)
|
||||
|
||||
with self.assertQueryCount(__system__=28, employee=29):
|
||||
with self.assertQueryCount(__system__=29, employee=30):
|
||||
rec.write({
|
||||
'name': 'Test2',
|
||||
'customer_id': customer_id,
|
||||
@@ -922,7 +1081,7 @@ class TestMailComplexPerformance(BaseMailPerformance):
|
||||
messages.flush()
|
||||
messages.invalidate_cache()
|
||||
|
||||
with self.assertQueryCount(employee=13):
|
||||
with self.assertQueryCount(employee=13): # tm only: 12
|
||||
res = messages.message_format()
|
||||
self.assertEqual(len(res), 6)
|
||||
|
||||
@@ -934,96 +1093,87 @@ class TestMailHeavyPerformancePost(BaseMailPerformance):
|
||||
super(TestMailHeavyPerformancePost, self).setUp()
|
||||
|
||||
# record
|
||||
self.record = self.env['mail.test.container'].with_context(mail_create_nosubscribe=True).create({
|
||||
self.record_container = self.env['mail.test.container'].with_context(mail_create_nosubscribe=True).create({
|
||||
'name': 'Test record',
|
||||
'customer_id': self.customer.id,
|
||||
'alias_name': 'test-alias',
|
||||
})
|
||||
# followers
|
||||
self.user_follower_email = self.env['res.users'].with_context(self._quick_create_ctx).create({
|
||||
self.user_follower_email = self.env['res.users'].with_context(self._test_context).create({
|
||||
'name': 'user_follower_email',
|
||||
'login': 'user_follower_email',
|
||||
'email': 'user_follower_email@example.com',
|
||||
'notification_type': 'email',
|
||||
'groups_id': [(6, 0, [self.env.ref('base.group_user').id])],
|
||||
})
|
||||
self.user_follower_inbox = self.env['res.users'].with_context(self._quick_create_ctx).create({
|
||||
self.user_follower_inbox = self.env['res.users'].with_context(self._test_context).create({
|
||||
'name': 'user_follower_inbox',
|
||||
'login': 'user_follower_inbox',
|
||||
'email': 'user_follower_inbox@example.com',
|
||||
'notification_type': 'inbox',
|
||||
'groups_id': [(6, 0, [self.env.ref('base.group_user').id])],
|
||||
})
|
||||
self.partner_follower = self.env['res.partner'].with_context(self._quick_create_ctx).create({
|
||||
self.partner_follower = self.env['res.partner'].with_context(self._test_context).create({
|
||||
'name': 'partner_follower',
|
||||
'email': 'partner_follower@example.com',
|
||||
})
|
||||
self.record.message_subscribe([
|
||||
self.record_container.message_subscribe([
|
||||
self.partner_follower.id,
|
||||
self.user_follower_inbox.partner_id.id,
|
||||
self.user_follower_email.partner_id.id
|
||||
])
|
||||
|
||||
# partner_ids
|
||||
self.user_inbox = self.env['res.users'].with_context(self._quick_create_ctx).create({
|
||||
self.user_inbox = self.env['res.users'].with_context(self._test_context).create({
|
||||
'name': 'user_inbox',
|
||||
'login': 'user_inbox',
|
||||
'email': 'user_inbox@example.com',
|
||||
'notification_type': 'inbox',
|
||||
'groups_id': [(6, 0, [self.env.ref('base.group_user').id])],
|
||||
})
|
||||
self.user_email = self.env['res.users'].with_context(self._quick_create_ctx).create({
|
||||
self.user_email = self.env['res.users'].with_context(self._test_context).create({
|
||||
'name': 'user_email',
|
||||
'login': 'user_email',
|
||||
'email': 'user_email@example.com',
|
||||
'notification_type': 'email',
|
||||
'groups_id': [(6, 0, [self.env.ref('base.group_user').id])],
|
||||
})
|
||||
self.partner = self.env['res.partner'].with_context(self._quick_create_ctx).create({
|
||||
self.partner = self.env['res.partner'].with_context(self._test_context).create({
|
||||
'name': 'partner',
|
||||
'email': 'partner@example.com',
|
||||
})
|
||||
self.vals = [{
|
||||
'datas': base64.b64encode(bytes("attachement content %s" % i, 'utf-8')),
|
||||
'name': 'fileText_test%s.txt' % i,
|
||||
'mimetype': 'text/plain',
|
||||
'res_model': 'mail.compose.message',
|
||||
'res_id': 0,
|
||||
} for i in range(3)]
|
||||
|
||||
self._init_mail_gateway()
|
||||
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
@users('employee')
|
||||
@warmup
|
||||
def test_complete_message_post(self):
|
||||
# aims to cover as much features of message_post as possible
|
||||
partner_ids = [self.user_inbox.partner_id.id, self.user_email.partner_id.id, self.partner.id]
|
||||
record = self.record.with_user(self.env.user)
|
||||
attachements = [ # not linear on number of attachements
|
||||
recipients = self.user_inbox.partner_id + self.user_email.partner_id + self.partner
|
||||
record_container = self.record_container.with_user(self.env.user)
|
||||
attachments_vals = [ # not linear on number of attachments_vals
|
||||
('attach tuple 1', "attachement tupple content 1"),
|
||||
('attach tuple 2', "attachement tupple content 2", {'cid': 'cid1'}),
|
||||
('attach tuple 3', "attachement tupple content 3", {'cid': 'cid2'}),
|
||||
]
|
||||
self.attachements = self.env['ir.attachment'].with_user(self.env.user).create(self.vals)
|
||||
attachement_ids = self.attachements.ids
|
||||
with self.assertQueryCount(employee=67):
|
||||
attachments = self.env['ir.attachment'].with_user(self.env.user).create(self.test_attachments_vals)
|
||||
with self.assertQueryCount(employee=68):
|
||||
self.cr.sql_log = self.warm and self.cr.sql_log_count
|
||||
record.with_context({}).message_post(
|
||||
record_container.with_context({}).message_post(
|
||||
body='<p>Test body <img src="cid:cid1"> <img src="cid:cid2"></p>',
|
||||
subject='Test Subject',
|
||||
message_type='notification',
|
||||
subtype_xmlid=None,
|
||||
partner_ids=partner_ids,
|
||||
partner_ids=recipients.ids,
|
||||
parent_id=False,
|
||||
attachments=attachements,
|
||||
attachment_ids=attachement_ids,
|
||||
attachments=attachments_vals,
|
||||
attachment_ids=attachments.ids,
|
||||
email_add_signature=True,
|
||||
model_description=False,
|
||||
mail_auto_delete=True
|
||||
)
|
||||
self.cr.sql_log = False
|
||||
self.assertTrue(record.message_ids[0].body.startswith('<p>Test body <img src="/web/image/'))
|
||||
self.assertEqual(self.attachements.mapped('res_model'), [record._name for i in range(3)])
|
||||
self.assertEqual(self.attachements.mapped('res_id'), [record.id for i in range(3)])
|
||||
# self.assertEqual(record.message_ids[0].notified_partner_ids, [])
|
||||
new_message = record_container.message_ids[0]
|
||||
self.assertEqual(attachments.mapped('res_model'), [record_container._name for i in range(3)])
|
||||
self.assertEqual(attachments.mapped('res_id'), [record_container.id for i in range(3)])
|
||||
self.assertTrue(new_message.body.startswith('<p>Test body <img src="/web/image/'))
|
||||
self.assertEqual(new_message.notified_partner_ids, recipients)
|
||||
|
||||
@@ -15,6 +15,8 @@ real applications. """,
|
||||
'test_mass_mailing',
|
||||
'mail',
|
||||
'mail_bot',
|
||||
'portal',
|
||||
'rating',
|
||||
# 'snailmail',
|
||||
'mass_mailing',
|
||||
'mass_mailing_sms',
|
||||
@@ -23,6 +25,7 @@ real applications. """,
|
||||
],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'security/ir_rule_data.xml',
|
||||
],
|
||||
'demo': [
|
||||
],
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import test_mail_models
|
||||
from . import test_mail_models_mail
|
||||
from . import test_mail_models_sms
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class MailTestRating(models.Model):
|
||||
""" A model inheriting from mail.thread with some fields used for SMS
|
||||
gateway, like a partner, a specific mobile phone, ... """
|
||||
_description = 'Rating Model (ticket-like)'
|
||||
_name = 'mail.test.rating'
|
||||
_inherit = [
|
||||
'mail.thread',
|
||||
'mail.activity.mixin',
|
||||
'rating.mixin',
|
||||
'portal.mixin',
|
||||
]
|
||||
_mailing_enabled = True
|
||||
_order = 'name asc, id asc'
|
||||
|
||||
name = fields.Char()
|
||||
subject = fields.Char()
|
||||
company_id = fields.Many2one('res.company', 'Company')
|
||||
customer_id = fields.Many2one('res.partner', 'Customer')
|
||||
email_from = fields.Char(compute='_compute_email_from', precompute=True, readonly=False, store=True)
|
||||
mobile_nbr = fields.Char(compute='_compute_mobile_nbr', precompute=True, readonly=False, store=True)
|
||||
phone_nbr = fields.Char(compute='_compute_phone_nbr', precompute=True, readonly=False, store=True)
|
||||
user_id = fields.Many2one('res.users', 'Responsible', tracking=1)
|
||||
|
||||
@api.depends('customer_id')
|
||||
def _compute_email_from(self):
|
||||
for rating in self:
|
||||
if rating.customer_id.email_normalized:
|
||||
rating.email_from = rating.customer_id.email_normalized
|
||||
elif not rating.email_from:
|
||||
rating.email_from = False
|
||||
|
||||
@api.depends('customer_id')
|
||||
def _compute_mobile_nbr(self):
|
||||
for rating in self:
|
||||
if rating.customer_id.mobile:
|
||||
rating.mobile_nbr = rating.customer_id.mobile
|
||||
elif not rating.mobile_nbr:
|
||||
rating.mobile_nbr = False
|
||||
|
||||
@api.depends('customer_id')
|
||||
def _compute_phone_nbr(self):
|
||||
for rating in self:
|
||||
if rating.customer_id.phone:
|
||||
rating.phone_nbr = rating.customer_id.phone
|
||||
elif not rating.phone_nbr:
|
||||
rating.phone_nbr = False
|
||||
|
||||
def rating_get_partner_id(self):
|
||||
return self.customer_id
|
||||
@@ -1,4 +1,7 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_mail_test_rating_all,mail.test.rating.all,model_mail_test_rating,,0,0,0,0
|
||||
access_mail_test_rating_portal,mail.test.rating.portal,model_mail_test_rating,base.group_portal,1,0,0,0
|
||||
access_mail_test_rating_user,mail.test.rating.user,model_mail_test_rating,base.group_user,1,1,1,1
|
||||
access_mail_test_sms_all,mail.test.sms.all,model_mail_test_sms,,0,0,0,0
|
||||
access_mail_test_sms_user,mail.test.sms.user,model_mail_test_sms,base.group_user,1,1,1,1
|
||||
access_mail_test_sms_bl_all,mail.test.sms.bl.all,model_mail_test_sms_bl,,0,0,0,0
|
||||
|
||||
|
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
|
||||
<record id="mail_test_rating_rule_mc" model="ir.rule">
|
||||
<field name="name">TestRating: Multi Company</field>
|
||||
<field name="model_id" ref="test_mail_full.model_mail_test_rating"/>
|
||||
<field eval="True" name="global"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
<record id="mail_test_rating_rule_portal" model="ir.rule">
|
||||
<field name="name">TestRating: Portal should follow</field>
|
||||
<field name="model_id" ref="test_mail_full.model_mail_test_rating"/>
|
||||
<field name="domain_force">[('message_partner_ids', 'in', [user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
from . import common
|
||||
from . import test_odoobot
|
||||
from . import test_mail_performance
|
||||
from . import test_phone_blacklist
|
||||
from . import test_mass_mailing
|
||||
from . import test_mass_mailing_statistics
|
||||
from . import test_mass_sms
|
||||
from . import test_rating
|
||||
from . import test_sms_composer
|
||||
from . import test_sms_management
|
||||
from . import test_sms_performance
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.mail.tests.common import mail_new_test_user
|
||||
from odoo.addons.test_mail.tests.test_performance import BaseMailPerformance
|
||||
from odoo.tests.common import users, warmup
|
||||
from odoo.tests import tagged
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
@tagged('mail_performance')
|
||||
class TestMailPerformance(BaseMailPerformance):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMailPerformance, cls).setUpClass()
|
||||
|
||||
# users / followers
|
||||
cls.user_emp_email = mail_new_test_user(
|
||||
cls.env,
|
||||
company_id=cls.user_admin.company_id.id,
|
||||
company_ids=[(4, cls.user_admin.company_id.id)],
|
||||
email='user.emp.email@test.example.com',
|
||||
login='user_emp_email',
|
||||
groups='base.group_user,base.group_partner_manager',
|
||||
name='Emmanuel Email',
|
||||
notification_type='email',
|
||||
signature='--\nEmmanuel',
|
||||
)
|
||||
cls.user_portal = mail_new_test_user(
|
||||
cls.env,
|
||||
company_id=cls.user_admin.company_id.id,
|
||||
company_ids=[(4, cls.user_admin.company_id.id)],
|
||||
email='user.portal@test.example.com',
|
||||
login='user_portal',
|
||||
groups='base.group_portal',
|
||||
name='Paul Portal',
|
||||
)
|
||||
cls.customers = cls.env['res.partner'].create([
|
||||
{'country_id': cls.env.ref('base.be').id,
|
||||
'email': 'customer.full.test.1@example.com',
|
||||
'name': 'Test Full Customer 1',
|
||||
'mobile': '0456112233',
|
||||
'phone': '0456112233',
|
||||
},
|
||||
{'country_id': cls.env.ref('base.be').id,
|
||||
'email': 'customer.full.test.2@example.com',
|
||||
'name': 'Test Full Customer 2',
|
||||
'mobile': '0456223344',
|
||||
'phone': '0456112233',
|
||||
},
|
||||
])
|
||||
|
||||
# record
|
||||
cls.record_container = cls.env['mail.test.container.mc'].create({
|
||||
'alias_name': 'test-alias',
|
||||
'customer_id': cls.customer.id,
|
||||
'name': 'Test Container',
|
||||
})
|
||||
cls.record_ticket = cls.env['mail.test.ticket.mc'].create({
|
||||
'email_from': 'email.from@test.example.com',
|
||||
'container_id': cls.record_container.id,
|
||||
'customer_id': False,
|
||||
'name': 'Test Ticket',
|
||||
'user_id': cls.user_emp_email.id,
|
||||
})
|
||||
cls.record_ticket.message_subscribe(cls.customers.ids + cls.user_admin.partner_id.ids + cls.user_portal.partner_id.ids)
|
||||
|
||||
def test_initial_values(self):
|
||||
""" Simply ensure some values through all tests """
|
||||
record_ticket = self.env['mail.test.ticket.mc'].browse(self.record_ticket.ids)
|
||||
self.assertEqual(record_ticket.message_partner_ids,
|
||||
self.user_emp_email.partner_id + self.user_admin.partner_id + self.customers + self.user_portal.partner_id)
|
||||
self.assertEqual(len(record_ticket.message_ids), 1)
|
||||
|
||||
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
@users('employee')
|
||||
@warmup
|
||||
def test_message_post_w_followers(self):
|
||||
""" Aims to cover as much features of message_post as possible """
|
||||
record_ticket = self.env['mail.test.ticket.mc'].browse(self.record_ticket.ids)
|
||||
attachments = self.env['ir.attachment'].create(self.test_attachments_vals)
|
||||
|
||||
with self.assertQueryCount(employee=102): # tmf: 93 / com: 100
|
||||
new_message = record_ticket.message_post(
|
||||
attachment_ids=attachments.ids,
|
||||
body='<p>Test Content</p>',
|
||||
message_type='comment',
|
||||
subject='Test Subject',
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
new_message.notified_partner_ids,
|
||||
self.user_emp_email.partner_id + self.user_admin.partner_id + self.customers + self.user_portal.partner_id
|
||||
)
|
||||
@@ -0,0 +1,74 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon, TestMailFullRecipients
|
||||
from odoo.tests import tagged
|
||||
from odoo.tests.common import users
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
@tagged('rating')
|
||||
class TestRatingFlow(TestMailFullCommon, TestMailFullRecipients):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestRatingFlow, cls).setUpClass()
|
||||
|
||||
cls.record_rating = cls.env['mail.test.rating'].create({
|
||||
'customer_id': cls.partner_1.id,
|
||||
'name': 'Test Rating',
|
||||
'user_id': cls.user_admin.id,
|
||||
})
|
||||
|
||||
def test_initial_values(self):
|
||||
record_rating = self.env['mail.test.rating'].browse(self.record_rating.ids)
|
||||
self.assertFalse(record_rating.rating_ids)
|
||||
self.assertEqual(record_rating.message_partner_ids, self.partner_admin)
|
||||
self.assertEqual(len(record_rating.message_ids), 1)
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_rating_prepare(self):
|
||||
record_rating = self.env['mail.test.rating'].browse(self.record_rating.ids)
|
||||
|
||||
# prepare rating token
|
||||
access_token = record_rating.rating_get_access_token()
|
||||
record_rating.invalidate_cache(fnames=['rating_ids'])
|
||||
|
||||
# check rating creation
|
||||
rating = record_rating.rating_ids
|
||||
self.assertEqual(rating.access_token, access_token)
|
||||
self.assertFalse(rating.consumed)
|
||||
self.assertFalse(rating.is_internal)
|
||||
self.assertEqual(rating.partner_id, self.partner_1)
|
||||
self.assertEqual(rating.rated_partner_id, self.user_admin.partner_id)
|
||||
self.assertFalse(rating.rating)
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_rating_rating_apply(self):
|
||||
record_rating = self.env['mail.test.rating'].browse(self.record_rating.ids)
|
||||
|
||||
# prepare rating token
|
||||
access_token = record_rating.rating_get_access_token()
|
||||
record_rating.invalidate_cache(fnames=['rating_ids'])
|
||||
|
||||
# apply a rate
|
||||
with self.mock_mail_gateway(mail_unlink_sent=False), self.mock_mail_app():
|
||||
record_rating.rating_apply(5, token=access_token, feedback='Top Feedback')
|
||||
message = record_rating.message_ids[0]
|
||||
rating = record_rating.rating_ids
|
||||
|
||||
# check posted message
|
||||
self.assertIn('Top Feedback', message.body)
|
||||
self.assertIn('rating/static/src/img/rating_5.png', message.body)
|
||||
self.assertEqual(message.author_id, self.partner_1)
|
||||
self.assertFalse(message.rating_ids)
|
||||
self.assertEqual(message.notified_partner_ids, self.partner_admin)
|
||||
self.assertEqual(message.subtype_id, self.env.ref('mail.mt_comment'))
|
||||
|
||||
# check rating update
|
||||
self.assertTrue(rating.consumed)
|
||||
self.assertEqual(rating.feedback, 'Top Feedback')
|
||||
self.assertFalse(rating.message_id)
|
||||
self.assertEqual(rating.rating, 5)
|
||||
@@ -14,14 +14,14 @@ class TestSMSPerformance(BaseMailPerformance, sms_common.SMSCase):
|
||||
def setUp(self):
|
||||
super(TestSMSPerformance, self).setUp()
|
||||
|
||||
self.test_record = self.env['mail.test.sms'].with_context(self._quick_create_ctx).create({
|
||||
self.test_record = self.env['mail.test.sms'].with_context(self._test_context).create({
|
||||
'name': 'Test',
|
||||
'customer_id': self.customer.id,
|
||||
'phone_nbr': '0456999999',
|
||||
})
|
||||
|
||||
# prepare recipients to test for more realistic workload
|
||||
self.partners = self.env['res.partner'].with_context(self._quick_create_ctx).create([
|
||||
self.partners = self.env['res.partner'].with_context(self._test_context).create([
|
||||
{'name': 'Test %s' % x,
|
||||
'email': 'test%s@example.com' % x,
|
||||
'mobile': '0456%s%s0000' % (x, x),
|
||||
@@ -29,8 +29,6 @@ class TestSMSPerformance(BaseMailPerformance, sms_common.SMSCase):
|
||||
} for x in range(0, 10)
|
||||
])
|
||||
|
||||
self._init_mail_gateway()
|
||||
|
||||
@mute_logger('odoo.addons.sms.models.sms_sms')
|
||||
@users('employee')
|
||||
@warmup
|
||||
@@ -87,13 +85,13 @@ class TestSMSMassPerformance(BaseMailPerformance, sms_common.MockSMS):
|
||||
records = self.env['mail.test.sms']
|
||||
partners = self.env['res.partner']
|
||||
for x in range(50):
|
||||
partners += self.env['res.partner'].with_context(**self._quick_create_ctx).create({
|
||||
partners += self.env['res.partner'].with_context(**self._test_context).create({
|
||||
'name': 'Partner_%s' % (x),
|
||||
'email': '_test_partner_%s@example.com' % (x),
|
||||
'country_id': be_country_id,
|
||||
'mobile': '047500%02d%02d' % (x, x)
|
||||
})
|
||||
records += self.env['mail.test.sms'].with_context(**self._quick_create_ctx).create({
|
||||
records += self.env['mail.test.sms'].with_context(**self._test_context).create({
|
||||
'name': 'Test_%s' % (x),
|
||||
'customer_id': partners[x].id,
|
||||
})
|
||||
|
||||
@@ -2,20 +2,17 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.test_mass_mailing.tests.common import TestMassMailCommon
|
||||
from odoo.addons.base.tests.common import MockSmtplibCase
|
||||
from odoo.tests import tagged
|
||||
from odoo.tests.common import users
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
@tagged('mass_mailing')
|
||||
class TestMassMailingServer(TestMassMailCommon, MockSmtplibCase):
|
||||
class TestMassMailingServer(TestMassMailCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMassMailingServer, cls).setUpClass()
|
||||
cls._init_mail_gateway()
|
||||
cls.env['ir.mail_server'].search([]).unlink()
|
||||
cls._init_mail_servers()
|
||||
cls.recipients = cls._create_mailing_test_records(model='mailing.test.optout', count=8)
|
||||
|
||||
|
||||
@@ -2,39 +2,25 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.mail.tests.common import mail_new_test_user
|
||||
from odoo.tests.common import TransactionCase, users, warmup
|
||||
from odoo.addons.test_mail.tests.test_performance import BaseMailPerformance
|
||||
from odoo.tests.common import users, warmup
|
||||
from odoo.tests import tagged
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
class TestMassMailPerformanceBase(TransactionCase):
|
||||
class TestMassMailPerformanceBase(BaseMailPerformance):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMassMailPerformanceBase, self).setUp()
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMassMailPerformanceBase, cls).setUpClass()
|
||||
|
||||
self.user_employee = mail_new_test_user(
|
||||
self.env, login='emp',
|
||||
groups='base.group_user',
|
||||
name='Ernest Employee', notification_type='inbox')
|
||||
|
||||
self.user_marketing = mail_new_test_user(
|
||||
self.env, login='marketing',
|
||||
cls.user_marketing = mail_new_test_user(
|
||||
cls.env,
|
||||
groups='base.group_user,mass_mailing.group_mass_mailing_user',
|
||||
name='Martial Marketing', signature='--\nMartial')
|
||||
|
||||
# setup mail gateway
|
||||
self.alias_domain = 'example.com'
|
||||
self.alias_catchall = 'catchall.test'
|
||||
self.alias_bounce = 'bounce.test'
|
||||
self.default_from = 'notifications'
|
||||
self.env['ir.config_parameter'].set_param('mail.bounce.alias', self.alias_bounce)
|
||||
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)
|
||||
self.env['ir.config_parameter'].set_param('mail.default.from', self.default_from)
|
||||
|
||||
# patch registry to simulate a ready environment
|
||||
self.patch(self.env.registry, 'ready', True)
|
||||
|
||||
login='marketing',
|
||||
name='Martial Marketing',
|
||||
signature='--\nMartial'
|
||||
)
|
||||
|
||||
@tagged('mail_performance')
|
||||
class TestMassMailPerformance(TestMassMailPerformanceBase):
|
||||
@@ -60,8 +46,8 @@ class TestMassMailPerformance(TestMassMailPerformanceBase):
|
||||
'mailing_domain': [('id', 'in', self.mm_recs.ids)],
|
||||
})
|
||||
|
||||
# runbot needs +101 compared to local (1568)
|
||||
with self.assertQueryCount(__system__=1670, marketing=1671):
|
||||
# runbot needs +101 compared to local (1570)
|
||||
with self.assertQueryCount(__system__=1672, marketing=1673):
|
||||
mailing.action_send_mail()
|
||||
|
||||
self.assertEqual(mailing.sent, 50)
|
||||
@@ -100,8 +86,8 @@ class TestMassMailBlPerformance(TestMassMailPerformanceBase):
|
||||
'mailing_domain': [('id', 'in', self.mm_recs.ids)],
|
||||
})
|
||||
|
||||
# runbot needs +125 compared to local (1834)
|
||||
with self.assertQueryCount(__system__=1960, marketing=1961):
|
||||
# runbot needs +125 compared to local (1836)
|
||||
with self.assertQueryCount(__system__=1962, marketing=1963):
|
||||
mailing.action_send_mail()
|
||||
|
||||
self.assertEqual(mailing.sent, 50)
|
||||
|
||||
@@ -252,14 +252,14 @@ class MockSmtplibCase:
|
||||
self.testing_smtp_session = TestingSMTPSession()
|
||||
|
||||
IrMailServer = self.env['ir.mail_server']
|
||||
connect = IrMailServer.connect
|
||||
find_mail_server = IrMailServer._find_mail_server
|
||||
connect_origin = IrMailServer.connect
|
||||
find_mail_server_origin = IrMailServer._find_mail_server
|
||||
|
||||
with patch.object(type(IrMailServer), '_is_test_mode', lambda self: False), \
|
||||
patch('smtplib.SMTP_SSL', side_effect=lambda *args, **kwargs: self.testing_smtp_session), \
|
||||
with patch('smtplib.SMTP_SSL', side_effect=lambda *args, **kwargs: self.testing_smtp_session), \
|
||||
patch('smtplib.SMTP', side_effect=lambda *args, **kwargs: self.testing_smtp_session), \
|
||||
patch.object(type(IrMailServer), 'connect', side_effect=connect) as connect_mocked, \
|
||||
patch.object(type(IrMailServer), '_find_mail_server', side_effect=find_mail_server) as find_mail_server_mocked:
|
||||
patch.object(type(IrMailServer), '_is_test_mode', lambda self: False), \
|
||||
patch.object(type(IrMailServer), 'connect', wraps=IrMailServer, side_effect=connect_origin) as connect_mocked, \
|
||||
patch.object(type(IrMailServer), '_find_mail_server', side_effect=find_mail_server_origin) as find_mail_server_mocked:
|
||||
self.connect_mocked = connect_mocked
|
||||
self.find_mail_server_mocked = find_mail_server_mocked
|
||||
yield
|
||||
@@ -298,14 +298,16 @@ class MockSmtplibCase:
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _init_mail_servers(cls):
|
||||
cls.env['ir.config_parameter'].sudo().set_param('mail.catchall.domain', 'test.com')
|
||||
cls.env['ir.config_parameter'].sudo().set_param('mail.default.from', 'notifications')
|
||||
cls.env['ir.config_parameter'].sudo().set_param('mail.bounce.alias', 'bounce')
|
||||
|
||||
cls.alias_bounce = 'bounce'
|
||||
def _init_mail_config(cls):
|
||||
cls.alias_bounce = 'bounce.test'
|
||||
cls.alias_domain = 'test.com'
|
||||
cls.default_from = 'notifications'
|
||||
cls.env['ir.config_parameter'].sudo().set_param('mail.catchall.domain', cls.alias_domain)
|
||||
cls.env['ir.config_parameter'].sudo().set_param('mail.default.from', cls.default_from)
|
||||
cls.env['ir.config_parameter'].sudo().set_param('mail.bounce.alias', cls.alias_bounce)
|
||||
|
||||
@classmethod
|
||||
def _init_mail_servers(cls):
|
||||
cls.env['ir.mail_server'].search([]).unlink()
|
||||
|
||||
ir_mail_server_values = {
|
||||
|
||||
@@ -15,6 +15,7 @@ from odoo.tools import mute_logger
|
||||
class TestIrMailServer(TransactionCase, MockSmtplibCase):
|
||||
|
||||
def setUp(self):
|
||||
self._init_mail_config()
|
||||
self._init_mail_servers()
|
||||
|
||||
def _build_email(self, mail_from, return_path=None):
|
||||
@@ -231,7 +232,7 @@ class TestIrMailServer(TransactionCase, MockSmtplibCase):
|
||||
self.assertEqual(len(self.emails), 1)
|
||||
|
||||
self.assert_email_sent_smtp(
|
||||
smtp_from='bounce@xn--9caaaaaaa.com',
|
||||
smtp_from='bounce.test@xn--9caaaaaaa.com',
|
||||
smtp_to_list=['dest@xn--example--i1a.com'],
|
||||
message_from='test@=?utf-8?b?w6nDqcOpw6nDqcOpw6k=?=.com',
|
||||
from_filter=False,
|
||||
@@ -322,7 +323,7 @@ class TestIrMailServer(TransactionCase, MockSmtplibCase):
|
||||
)
|
||||
|
||||
@mute_logger('odoo.models.unlink')
|
||||
@patch.dict("odoo.tools.config.options", {"from_filter": "test.com"})
|
||||
@patch.dict("odoo.tools.config.options", {"from_filter": "test.com", "smtp_server": "example.com"})
|
||||
def test_mail_server_binary_arguments_domain(self):
|
||||
"""Test the configuration provided in the odoo-bin arguments.
|
||||
|
||||
@@ -374,7 +375,7 @@ class TestIrMailServer(TransactionCase, MockSmtplibCase):
|
||||
)
|
||||
|
||||
@mute_logger('odoo.models.unlink')
|
||||
@patch.dict("odoo.tools.config.options", {"from_filter": "test.com"})
|
||||
@patch.dict("odoo.tools.config.options", {"from_filter": "test.com", "smtp_server": "example.com"})
|
||||
def test_mail_server_binary_arguments_domain_smtp_session(self):
|
||||
"""Test the configuration provided in the odoo-bin arguments.
|
||||
|
||||
@@ -417,7 +418,7 @@ class TestIrMailServer(TransactionCase, MockSmtplibCase):
|
||||
)
|
||||
|
||||
@mute_logger('odoo.models.unlink')
|
||||
@patch.dict('odoo.tools.config.options', {'from_filter': 'test.com'})
|
||||
@patch.dict('odoo.tools.config.options', {'from_filter': 'test.com', 'smtp_server': 'example.com'})
|
||||
def test_mail_server_mail_default_from_filter(self):
|
||||
"""Test that the config parameter "mail.default.from_filter" overwrite the odoo-bin
|
||||
argument "--from-filter"
|
||||
|
||||
Reference in New Issue
Block a user