diff --git a/addons/mail/tests/common.py b/addons/mail/tests/common.py index 2fe5f1bcb1b..4277c53892b 100644 --- a/addons/mail/tests/common.py +++ b/addons/mail/tests/common.py @@ -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 ', 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)] diff --git a/addons/mail/tests/test_mail_channel_partner.py b/addons/mail/tests/test_mail_channel_partner.py index 8f6e8a66424..f7ba426648f 100644 --- a/addons/mail/tests/test_mail_channel_partner.py +++ b/addons/mail/tests/test_mail_channel_partner.py @@ -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') diff --git a/addons/test_mail/tests/common.py b/addons/test_mail/tests/common.py index ae43c3ae437..88759108d48 100644 --- a/addons/test_mail/tests/common.py +++ b/addons/test_mail/tests/common.py @@ -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 diff --git a/addons/test_mail/tests/test_mail_composer.py b/addons/test_mail/tests/test_mail_composer.py index 01c6587ae17..57f4adfbadd 100644 --- a/addons/test_mail/tests/test_mail_composer.py +++ b/addons/test_mail/tests/test_mail_composer.py @@ -18,7 +18,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({ @@ -609,8 +608,8 @@ class TestComposerResultsComment(TestMailComposer): 'email_from': self.test_record.user_id.email_formatted, # set by template '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'}, ] }, @@ -624,8 +623,8 @@ class TestComposerResultsComment(TestMailComposer): 'email_from': self.test_record.user_id.email_formatted, # set by template '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 +637,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)) diff --git a/addons/test_mail/tests/test_mail_composer_mixin.py b/addons/test_mail/tests/test_mail_composer_mixin.py index d13473f7801..5b85c34ed5c 100644 --- a/addons/test_mail/tests/test_mail_composer_mixin.py +++ b/addons/test_mail/tests/test_mail_composer_mixin.py @@ -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 }}', diff --git a/addons/test_mail/tests/test_mail_followers.py b/addons/test_mail/tests/test_mail_followers.py index 8e6a54c0501..4a1e0d94258 100644 --- a/addons/test_mail/tests/test_mail_followers.py +++ b/addons/test_mail/tests/test_mail_followers.py @@ -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)]}) diff --git a/addons/test_mail/tests/test_mail_gateway.py b/addons/test_mail/tests/test_mail_gateway.py index aff9f63bf71..d5e1e669325 100644 --- a/addons/test_mail/tests/test_mail_gateway.py +++ b/addons/test_mail/tests/test_mail_gateway.py @@ -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', diff --git a/addons/test_mail/tests/test_mail_mail.py b/addons/test_mail/tests/test_mail_mail.py index 04f48e1a992..0f587e54c02 100644 --- a/addons/test_mail/tests/test_mail_mail.py +++ b/addons/test_mail/tests/test_mail_mail.py @@ -5,19 +5,17 @@ import psycopg2 from unittest.mock import call from odoo import api -from odoo.addons.base.tests.common import MockSmtplibCase 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({ @@ -133,6 +131,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') diff --git a/addons/test_mail/tests/test_mail_message.py b/addons/test_mail/tests/test_mail_message.py index f4bfe292a68..0ebbc5e9f05 100644 --- a/addons/test_mail/tests/test_mail_message.py +++ b/addons/test_mail/tests/test_mail_message.py @@ -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', diff --git a/addons/test_mail/tests/test_mail_multicompany.py b/addons/test_mail/tests/test_mail_multicompany.py index 18082651e69..58309a7482f 100644 --- a/addons/test_mail/tests/test_mail_multicompany.py +++ b/addons/test_mail/tests/test_mail_multicompany.py @@ -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) diff --git a/addons/test_mail/tests/test_mail_thread_internals.py b/addons/test_mail/tests/test_mail_thread_internals.py index 58c7a0b2538..56b9258070a 100644 --- a/addons/test_mail/tests/test_mail_thread_internals.py +++ b/addons/test_mail/tests/test_mail_thread_internals.py @@ -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', diff --git a/addons/test_mail/tests/test_message_management.py b/addons/test_mail/tests/test_message_management.py index 57d24e47f92..e1e5ab203e9 100644 --- a/addons/test_mail/tests/test_message_management.py +++ b/addons/test_mail/tests/test_message_management.py @@ -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({}) diff --git a/addons/test_mail/tests/test_performance.py b/addons/test_mail/tests/test_performance.py index 29a014a18a2..a6076f63606 100644 --- a/addons/test_mail/tests/test_performance.py +++ b/addons/test_mail/tests/test_performance.py @@ -48,6 +48,7 @@ class BaseMailPerformance(TransactionCaseWithUserDemo): # patch registry to simulate a ready environment self.patch(self.env.registry, 'ready', True) self._flush_tracking() + self._init_mail_gateway() def _init_mail_gateway(self): # setup mail gateway @@ -113,8 +114,6 @@ class TestBaseMailPerformance(BaseMailPerformance): } ]) - self._init_mail_gateway() - @users('__system__', 'demo') @warmup def test_read_mail(self): @@ -223,8 +222,6 @@ 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}) @@ -531,10 +528,8 @@ class TestMailComplexPerformance(BaseMailPerformance): 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() @@ -991,8 +986,6 @@ class TestMailHeavyPerformancePost(BaseMailPerformance): '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 diff --git a/addons/test_mail_full/tests/test_sms_performance.py b/addons/test_mail_full/tests/test_sms_performance.py index 24108442039..1e63a832f0c 100644 --- a/addons/test_mail_full/tests/test_sms_performance.py +++ b/addons/test_mail_full/tests/test_sms_performance.py @@ -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 diff --git a/addons/test_mass_mailing/tests/test_mailing_server.py b/addons/test_mass_mailing/tests/test_mailing_server.py index 0bc1d35c222..53986f491a5 100644 --- a/addons/test_mass_mailing/tests/test_mailing_server.py +++ b/addons/test_mass_mailing/tests/test_mailing_server.py @@ -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) diff --git a/odoo/addons/base/tests/common.py b/odoo/addons/base/tests/common.py index 0fd845209db..28ddff19b06 100644 --- a/odoo/addons/base/tests/common.py +++ b/odoo/addons/base/tests/common.py @@ -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 = { diff --git a/odoo/addons/base/tests/test_ir_mail_server.py b/odoo/addons/base/tests/test_ir_mail_server.py index 448f04c2d06..c2a330067f9 100644 --- a/odoo/addons/base/tests/test_ir_mail_server.py +++ b/odoo/addons/base/tests/test_ir_mail_server.py @@ -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"