diff options
| author | Thibault Delavallée <tde@odoo.com> | 2019-10-21 12:51:32 +0000 |
|---|---|---|
| committer | Thibault Delavallée <tde@odoo.com> | 2020-11-26 08:45:55 +0000 |
| commit | def98d2375a8a906092293f0aa1ce03bf948d2d3 (patch) | |
| tree | 2136ce434aa8ba5912f8bf3dd39bea8c71dd2909 | |
| parent | 8c0e92cdcdf98daa3c841af97e0bd2e4b015a1b9 (diff) | |
[IMP] test_mail: add new mail composer tests for its internals
Purpose is to have some low level tests for composer itself allowing to
ensure its behavior. We add tests notably about default values computation
in mass mailing mode as well as template_id change and values synchronization
in composer model.
In a near future composer will probably be improved (use computed fields,
rewrite part of its logic to improve performances). Having tests done before
those tasks ensure we notice every change that might happen.
Task ID-2390314
PR odoo/odoo#62061
| -rw-r--r-- | addons/test_mail/data/template_data.xml | 12 | ||||
| -rw-r--r-- | addons/test_mail/tests/__init__.py | 1 | ||||
| -rw-r--r-- | addons/test_mail/tests/common.py | 23 | ||||
| -rw-r--r-- | addons/test_mail/tests/test_mail_composer.py | 317 | ||||
| -rw-r--r-- | addons/test_mail/tests/test_message_composer.py | 4 | ||||
| -rw-r--r-- | addons/test_mail_full/tests/common.py | 19 |
6 files changed, 359 insertions, 17 deletions
diff --git a/addons/test_mail/data/template_data.xml b/addons/test_mail/data/template_data.xml index 4716060d444..d7a9248f449 100644 --- a/addons/test_mail/data/template_data.xml +++ b/addons/test_mail/data/template_data.xml @@ -21,4 +21,16 @@ <template id="mail_test_ticket_tracking_view"> <p><span t-esc="object.name"/> datetime has been updated to <span t-esc="object.datetime"/></p> </template> + + <template id="mail_test_ticket_test_template"> + <t t-call="web.html_container"> + <t t-set="o" t-value="res_company"/> + <t t-call="web.external_layout"> + <div class="page"> + <p>This is a sample of an external report.</p> + </div> + </t> + </t> + </template> + </odoo> diff --git a/addons/test_mail/tests/__init__.py b/addons/test_mail/tests/__init__.py index 02ebd701f5c..e328b555861 100644 --- a/addons/test_mail/tests/__init__.py +++ b/addons/test_mail/tests/__init__.py @@ -3,6 +3,7 @@ from . import test_invite from . import test_ir_actions from . import test_mail_activity +from . import test_mail_composer from . import test_mail_followers from . import test_mail_message from . import test_mail_mail diff --git a/addons/test_mail/tests/common.py b/addons/test_mail/tests/common.py index b62b1a444aa..c556a988367 100644 --- a/addons/test_mail/tests/common.py +++ b/addons/test_mail/tests/common.py @@ -12,6 +12,29 @@ class TestMailCommon(MailCommon): 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 + 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)]) + + records = cls.env[model].with_context(**cls._test_context).create([{ + 'name': 'Test_%s' % (x), + 'customer_id': partners[x].id, + } for x in range(count)]) + + cls.records = cls._reset_mail_context(records) + cls.partners = partners + return cls.records, cls.partners + class TestMailMultiCompanyCommon(MailCommon): diff --git a/addons/test_mail/tests/test_mail_composer.py b/addons/test_mail/tests/test_mail_composer.py new file mode 100644 index 00000000000..beed5150276 --- /dev/null +++ b/addons/test_mail/tests/test_mail_composer.py @@ -0,0 +1,317 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import base64 + +from odoo.addons.mail.tests.common import mail_new_test_user +from odoo.addons.test_mail.tests.common import TestMailCommon, TestRecipients +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 """ + + @classmethod + def setUpClass(cls): + super(TestMailComposer, cls).setUpClass() + cls._init_mail_gateway() + + cls.user_employee_2 = mail_new_test_user( + cls.env, login='employee2', groups='base.group_user', + notification_type='inbox', email='eglantine@example.com', + name='Eglantine Employee', signature='--\nEglantine') + cls.partner_employee_2 = cls.user_employee_2.partner_id + + cls.test_record = cls.env['mail.test.ticket'].with_context(cls._test_context).create({ + 'name': 'TestRecord', + '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_report = cls.env['ir.actions.report'].create({ + 'name': 'Test Report on mail test ticket', + 'model': 'mail.test.ticket', + 'report_type': 'qweb-pdf', + 'report_name': 'test_mail.mail_test_ticket_test_template', + }) + + 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({ + 'name': 'TestTemplate', + 'subject': 'TemplateSubject ${object.name}', + 'body_html': '<p>TemplateBody ${object.name}</p>', + 'partner_to': '${object.customer_id.id if object.customer_id else ""}', + 'email_to': '${(object.email_from if not object.customer_id else "") | safe}', + 'email_from': '${object.user_id.email_formatted | safe}', + 'model_id': cls.env['ir.model']._get('mail.test.ticket').id, + 'mail_server_id': cls.mail_server.id, + }) + + def _generate_attachments_data(self, count): + return [{ + 'name': '%02d.txt' % x, + 'datas': base64.b64encode(b'Att%02d' % x), + } for x in range(count)] + + def _get_web_context(self, records, add_web=True, **values): + """ Helper to generate composer context. Will make tests a bit less + verbose. + + :param add_web: add web context, generally making noise especially in + mass mail mode (active_id/ids both present in context) + """ + base_context = { + 'default_model': records._name, + } + if len(records) == 1: + base_context['default_composition_mode'] = 'comment' + base_context['default_res_id'] = records.id + else: + base_context['default_composition_mode'] = 'mass_mail' + base_context['active_ids'] = records.ids + if add_web: + base_context['active_model'] = records._name + base_context['active_id'] = records[0].id + if values: + base_context.update(**values) + return base_context + + +@tagged('mail_composer') +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))) + 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.no_auto_thread) + self.assertEqual(composer_form.composition_mode, 'comment') + self.assertEqual(composer_form.model, self.test_records._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))) + # TDE FIXME: currently failing + # self.assertFalse(composer_form.subject, 'MailComposer: mass mode should have void default subject if no template') + # 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.no_auto_thread) + self.assertEqual(composer_form.composition_mode, 'mass_mail') + self.assertEqual(composer_form.model, self.test_records._name) + + @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') + self.assertEqual(composer_form.body, self.template.body_html, + 'MailComposer: mass mode should have template raw body if template') + # 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.no_auto_thread) + self.assertEqual(composer_form.composition_mode, 'mass_mail') + self.assertEqual(composer_form.model, self.test_records._name) + + +@tagged('mail_composer') +class TestComposerInternals(TestMailComposer): + + @users('employee') + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mail_composer_attachments_comment(self): + """ Test attachments management in comment mode. """ + attachment_data = self._generate_attachments_data(3) + self.template.write({ + 'attachment_ids': [(0, 0, a) for a in attachment_data], + 'report_template': self.test_report.id, + }) + attachs = self.env['ir.attachment'].search([('name', 'in', [a['name'] for a in attachment_data])]) + self.assertEqual(len(attachs), 3) + + composer = self.env['mail.compose.message'].with_context({ + 'default_composition_mode': 'comment', + 'default_model': self.test_record._name, + 'default_res_id': self.test_record.id, + 'default_template_id': self.template.id, + }).create({ + 'body': '<p>Test Body</p>', + }) + # currently onchange necessary + composer.onchange_template_id_wrapper() + + # values coming from template + self.assertEqual(len(composer.attachment_ids), 4) + for attach in attachs: + self.assertIn(attach, composer.attachment_ids) + generated = composer.attachment_ids - attachs + self.assertEqual(len(generated), 1, 'MailComposer: should have 1 additional attachment for report') + self.assertEqual(generated.res_model, 'mail.compose.message') + self.assertEqual(generated.res_id, 0) + + @users('employee') + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mail_composer_author(self): + """ Test author_id / email_from synchronization, in both comment and mass mail + modes. """ + for composition_mode in ['comment', 'mass_mail']: + 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) + composer = self.env['mail.compose.message'].with_context(ctx).create({ + 'body': '<p>Test Body</p>', + }) + + # default values are current user + self.assertEqual(composer.author_id, self.env.user.partner_id) + self.assertEqual(composer.email_from, self.env.user.email_formatted) + + # author values reset email (FIXME: currently not synchronized) + composer.write({'author_id': self.partner_1}) + self.assertEqual(composer.author_id, self.partner_1) + self.assertEqual(composer.email_from, self.env.user.email_formatted) + # self.assertEqual(composer.email_from, self.partner_1.email_formatted) + + # changing template should update its email_from + composer.write({'template_id': self.template.id, 'author_id': self.env.user.partner_id}) + # currently onchange necessary + composer.onchange_template_id_wrapper() + self.assertEqual(composer.author_id, self.env.user.partner_id, + 'MailComposer: should take value given by user') + if composition_mode == 'comment': + self.assertEqual(composer.email_from, self.test_record.user_id.email_formatted, + 'MailComposer: should take email_from rendered from template') + else: + self.assertEqual(composer.email_from, self.template.email_from, + 'MailComposer: should take email_from raw from template') + + # manual values are kept over template values + composer.write({'email_from': self.test_from}) + self.assertEqual(composer.author_id, self.env.user.partner_id) + self.assertEqual(composer.email_from, self.test_from) + + @users('employee') + def test_mail_composer_content_comment(self): + """ Test content management (subject, body, server) in comment mode. + Template update is also tested. """ + for composition_mode in ['comment', 'mass_mail']: + 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({ + 'subject': 'My amazing subject', + 'body': '<p>Test Body</p>', + }) + + # 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) + + # changing template should update its content + composer.write({'template_id': self.template.id}) + # currently onchange necessary + composer.onchange_template_id_wrapper() + + # values come from template + if composition_mode == 'comment': + 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) + 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) + + # manual values is kept over template + composer.write({'subject': 'Back to my amazing subject'}) + self.assertEqual(composer.subject, 'Back to my amazing subject') + + # reset template should reset values + composer.write({'template_id': False}) + # currently onchange necessary + composer.onchange_template_id_wrapper() + + # values are reset + if composition_mode == 'comment': + self.assertEqual(composer.subject, 'Re: %s' % self.test_record.name) + self.assertEqual(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) + else: + # values are reset TDE FIXME: strange for subject + self.assertEqual(composer.subject, 'Back to my amazing subject') + self.assertEqual(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) + + # 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.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) + 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) + + # 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.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) + 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) + + # 4. template + user input + ctx['default_template_id'] = self.template.id + composer = self.env['mail.compose.message'].with_context(ctx).create({ + 'subject': 'My amazing subject', + 'body': '<p>Test Body</p>', + 'mail_server_id': False, + }) + + # 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) diff --git a/addons/test_mail/tests/test_message_composer.py b/addons/test_mail/tests/test_message_composer.py index a93432a1575..ea6aa91803f 100644 --- a/addons/test_mail/tests/test_message_composer.py +++ b/addons/test_mail/tests/test_message_composer.py @@ -7,10 +7,13 @@ from unittest.mock import patch from odoo.addons.test_mail.tests.common import TestMailCommon, TestRecipients from odoo.addons.test_mail.models.test_mail_models import MailTestSimple +from odoo.tests import tagged from odoo.tools import mute_logger +@tagged('mail_composer') class TestComposer(TestMailCommon, TestRecipients): + """ Test Composer integration and results """ @classmethod def setUpClass(cls): @@ -153,6 +156,7 @@ class TestComposer(TestMailCommon, TestRecipients): self.assertEqual(self.test_record.message_ids[0].author_id, portal_user.partner_id) +@tagged('mail_composer') class TestComposerWTpl(TestMailCommon, TestRecipients): @classmethod diff --git a/addons/test_mail_full/tests/common.py b/addons/test_mail_full/tests/common.py index 10b2528b5ce..579ff6cb7ca 100644 --- a/addons/test_mail_full/tests/common.py +++ b/addons/test_mail_full/tests/common.py @@ -9,23 +9,8 @@ from odoo.addons.test_mass_mailing.tests.common import TestMassMailCommon class TestMailFullCommon(TestMassMailCommon, MassSMSCommon): @classmethod - def _create_records_for_batch(cls, model, count): - records = cls.env[model] - partners = cls.env['res.partner'] - country_id = cls.env.ref('base.be').id, - for x in range(count): - 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) - }) - records += cls.env[model].with_context(**cls._test_context).create({ - 'name': 'Test_%s' % (x), - 'customer_id': partners[x].id, - }) - cls.records = cls._reset_mail_context(records) - cls.partners = partners + def setUpClass(cls): + super(TestMailFullCommon, cls).setUpClass() class TestRecipients(TestRecipients): |
