diff --git a/addons/mail/tests/test_mail_composer.py b/addons/mail/tests/test_mail_composer.py index 11bde11084c..9b573efb5be 100644 --- a/addons/mail/tests/test_mail_composer.py +++ b/addons/mail/tests/test_mail_composer.py @@ -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' + ) diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index ce079a23cae..3fca30f5caf 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -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 diff --git a/addons/test_mail/tests/test_mail_composer.py b/addons/test_mail/tests/test_mail_composer.py index 8037497ca0d..c9ad9faf0e4 100644 --- a/addons/test_mail/tests/test_mail_composer.py +++ b/addons/test_mail/tests/test_mail_composer.py @@ -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 """ @@ -46,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', @@ -58,24 +62,17 @@ class TestMailComposer(TestMailCommon, TestRecipients): cls.test_from = '"John Doe" ' - 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': '

TemplateBody

', '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): @@ -107,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): @@ -155,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 @@ -169,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, '

TemplateBody %s

' % 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') @@ -293,6 +351,10 @@ class TestComposerInternals(TestMailComposer): self.assertEqual(composer.subject, 'My amazing subject') self.assertEqual(composer.body, '

Test Body

') 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}) @@ -304,10 +366,12 @@ class TestComposerInternals(TestMailComposer): self.assertEqual(composer.subject, 'TemplateSubject %s' % self.test_record.name) self.assertEqual(composer.body, '

TemplateBody %s

' % 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'}) @@ -321,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 @@ -346,10 +412,12 @@ class TestComposerInternals(TestMailComposer): self.assertEqual(composer.subject, 'TemplateSubject %s' % self.test_record.name) self.assertEqual(composer.body, '

TemplateBody %s

' % 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') @@ -364,10 +432,12 @@ class TestComposerInternals(TestMailComposer): self.assertEqual(composer.subject, 'TemplateSubject %s' % self.test_record.name) self.assertEqual(composer.body, '

TemplateBody %s

' % 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 @@ -375,15 +445,155 @@ class TestComposerInternals(TestMailComposer): 'subject': 'My amazing subject', 'body': '

Test Body

', 'mail_server_id': False, + 'record_name': 'CustomName', }) # creation values are taken self.assertEqual(composer.subject, 'My amazing subject') self.assertEqual(composer.body, '

Test Body

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

Test Body

', + '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': '

Test Body

', + '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. """ @@ -396,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, '

Test Body

') 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({ @@ -436,6 +648,7 @@ 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) @@ -489,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( @@ -506,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': '

Test Body

', + '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( @@ -526,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( @@ -543,8 +776,8 @@ class TestComposerResultsComment(TestMailComposer): composer._action_send_mail() message = self.test_record.message_ids[0] - self.assertEqual(message.body, '

Test Body

') self.assertEqual(message.author_id, self.user_employee.partner_id) + self.assertEqual(message.body, '

Test Body

') 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) @@ -609,6 +842,7 @@ 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': 'AttFileName_00.txt', 'raw': b'AttContent_00', 'type': 'text/plain'}, @@ -624,6 +858,7 @@ 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': 'AttFileName_00.txt', 'raw': b'AttContent_00', 'type': 'text/plain'}, @@ -658,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) @@ -681,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, '

TemplateBody %s

' % 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') @@ -714,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( @@ -754,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, '

TemplateBody %s

' % 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): @@ -843,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( diff --git a/addons/test_mail/tests/test_performance.py b/addons/test_mail/tests/test_performance.py index d02a2ef0006..43721eef50e 100644 --- a/addons/test_mail/tests/test_performance.py +++ b/addons/test_mail/tests/test_performance.py @@ -5,7 +5,7 @@ import base64 from odoo.addons.base.tests.common import TransactionCaseWithUserDemo from odoo.addons.mail.tests.common import MailCommon -from odoo.tests.common import users, warmup +from odoo.tests.common import users, warmup, Form from odoo.tests import tagged from odoo.tools import mute_logger, formataddr @@ -27,6 +27,10 @@ class BaseMailPerformance(MailCommon, TransactionCaseWithUserDemo): '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 @@ -206,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') @@ -231,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 !') @@ -246,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'}) @@ -259,7 +267,38 @@ class TestMailAPIPerformance(BaseMailPerformance): @users('__system__', 'employee') @warmup - @mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink') + @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) @@ -279,7 +318,59 @@ class TestMailAPIPerformance(BaseMailPerformance): @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': '

Test Body

', + '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 = '

Test Body

' + 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) @@ -300,11 +391,14 @@ class TestMailAPIPerformance(BaseMailPerformance): @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', @@ -317,9 +411,111 @@ class TestMailAPIPerformance(BaseMailPerformance): 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 @@ -885,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) @@ -897,7 +1093,7 @@ 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', @@ -921,7 +1117,7 @@ class TestMailHeavyPerformancePost(BaseMailPerformance): '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 @@ -946,45 +1142,38 @@ class TestMailHeavyPerformancePost(BaseMailPerformance): '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)] @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 + 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='

Test body

', 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('

Test body