diff --git a/addons/mail/tests/common.py b/addons/mail/tests/common.py index 3912398d5c3..675779e19e9 100644 --- a/addons/mail/tests/common.py +++ b/addons/mail/tests/common.py @@ -19,7 +19,7 @@ from odoo.addons.mail.models.mail_mail import MailMail from odoo.addons.mail.models.mail_message import Message from odoo.addons.mail.models.mail_notification import MailNotification from odoo.tests import common, new_test_user -from odoo.tools import formataddr, pycompat +from odoo.tools import formataddr, mute_logger, pycompat from odoo.tools.translate import code_translations mail_new_test_user = partial(new_test_user, context={'mail_create_nolog': True, @@ -1102,9 +1102,9 @@ class MailCommon(common.TransactionCase, MailCase): * 'English Layout for' -> Spanish Layout para * model * description: English: Lang Chatter Model (depends on test_record._name) - translated: Spanish description + translated: Spanish Model Description * module - * _('TestStuff') -> TestSpanishStuff (used as link button name in layout) + * _('NotificationButtonTitle') -> SpanishNotificationButtonTitle (used as link button name in layout) * _('View %s') -> SpanishView %s * template * body: English:

EnglishBody for

(depends on test_template.body) @@ -1114,17 +1114,22 @@ class MailCommon(common.TransactionCase, MailCase): """ # activate translations cls.env['res.lang']._activate_lang(lang_code) - cls.env.ref('base.module_base')._update_translations([lang_code]) + with mute_logger("odoo.addons.base.models.ir_module", "odoo.tools.translate"): + cls.env.ref('base.module_base')._update_translations([lang_code]) + cls.env.ref('base.module_mail')._update_translations([lang_code]) + cls.env.ref('base.module_test_mail')._update_translations([lang_code]) + code_translations.get_python_translations('mail', lang_code) + code_translations.get_python_translations('test_mail', lang_code) # Make sure Spanish translations have not been altered if test_record: - cls.env['ir.model']._get(test_record._name).with_context(lang=lang_code).name = 'Spanish description' + cls.env['ir.model']._get(test_record._name).with_context(lang=lang_code).name = 'Spanish Model Description' # Translate some code strings used in mailing - code_translations.python_translations[('test_mail', 'es_ES')] = {'TestStuff': 'TestSpanishStuff'} - cls.addClassCleanup(code_translations.python_translations.pop, ('test_mail', 'es_ES')) - code_translations.python_translations[('mail', 'es_ES')] = {'View %s': 'SpanishView %s'} - cls.addClassCleanup(code_translations.python_translations.pop, ('mail', 'es_ES')) + code_translations.python_translations[('test_mail', 'es_ES')]['NotificationButtonTitle'] = 'SpanishButtonTitle' + cls.addClassCleanup(code_translations.python_translations[('test_mail', 'es_ES')].pop, 'NotificationButtonTitle') + code_translations.python_translations[('mail', 'es_ES')]['View %s'] = 'SpanishView %s' + cls.addClassCleanup(code_translations.python_translations[('mail', 'es_ES')].pop, 'View %s') # Prepare some translated value for template if given if test_template: diff --git a/addons/test_mail/models/test_mail_corner_case_models.py b/addons/test_mail/models/test_mail_corner_case_models.py index e59aa431e40..31fd75ca27c 100644 --- a/addons/test_mail/models/test_mail_corner_case_models.py +++ b/addons/test_mail/models/test_mail_corner_case_models.py @@ -76,7 +76,7 @@ class MailTestLang(models.Model): group_options['has_button_access'] = True group_options['actions'] = [ {'url': self._notify_get_action_link('controller', controller='/test_mail/do_stuff', **local_msg_vals), - 'title': _('TestStuff')} + 'title': _('NotificationButtonTitle')} ] return groups diff --git a/addons/test_mail/models/test_mail_models.py b/addons/test_mail/models/test_mail_models.py index 8b3eec16f95..284e86956f6 100644 --- a/addons/test_mail/models/test_mail_models.py +++ b/addons/test_mail/models/test_mail_models.py @@ -225,7 +225,9 @@ class MailTestContainerMC(models.Model): class MailTestComposerMixin(models.Model): """ A simple invite-like wizard using the composer mixin, rendering on - itself. """ + composer source test model. Purpose is to have a minimal composer which + runs on other records and check notably dynamic template support and + translations. """ _description = 'Invite-like Wizard' _name = 'mail.test.composer.mixin' _inherit = ['mail.composer.mixin'] @@ -233,6 +235,25 @@ class MailTestComposerMixin(models.Model): name = fields.Char('Name') author_id = fields.Many2one('res.partner') description = fields.Html('Description', render_engine="qweb", render_options={"post_process": True}, sanitize=False) + source_ids = fields.Many2many('mail.test.composer.source', string='Invite source') def _compute_render_model(self): - self.render_model = self._name + self.render_model = 'mail.test.composer.source' + + +class MailTestComposerSource(models.Model): + """ A simple model on which invites are sent. """ + _description = 'Invite-like Wizard' + _name = 'mail.test.composer.source' + _inherit = ['mail.thread.blacklist'] + _primary_email = 'email_from' + + name = fields.Char('Name') + customer_id = fields.Many2one('res.partner', 'Main customer') + email_from = fields.Char( + 'Email', + compute='_compute_email_from', readonly=False, store=True) + + def _compute_email_from(self): + for source in self.filtered(lambda r: r.customer_id and not r.email_from): + source.email_from = source.customer_id.email_formatted diff --git a/addons/test_mail/security/ir.model.access.csv b/addons/test_mail/security/ir.model.access.csv index 0c6126ffb34..2fac058e400 100644 --- a/addons/test_mail/security/ir.model.access.csv +++ b/addons/test_mail/security/ir.model.access.csv @@ -19,6 +19,8 @@ access_mail_test_ticket_mc_portal,mail.test.ticket.mc.portal,model_mail_test_tic access_mail_test_ticket_mc_user,mail.test.ticket.mc.user,model_mail_test_ticket_mc,base.group_user,1,1,1,1 access_mail_test_composer_mixin_all,mail.test.composer.mixin.all,model_mail_test_composer_mixin,,0,0,0,0 access_mail_test_composer_mixin_user,mail.test.composer.mixin.user,model_mail_test_composer_mixin,base.group_user,1,1,1,1 +access_mail_test_composer_source_all,mail.test.composer.source.all,model_mail_test_composer_source,,1,0,0,0 +access_mail_test_composer_source_user,mail.test.composer.source.user,model_mail_test_composer_source,base.group_user,1,1,1,1 access_mail_test_container_portal,mail.test.container_portal,model_mail_test_container,base.group_portal,1,0,0,0 access_mail_test_container_user,mail.test.container.user,model_mail_test_container,base.group_user,1,1,1,1 access_mail_test_container_mc_portal,mail.test.container.mc.portal,model_mail_test_container_mc,base.group_portal,1,0,0,0 diff --git a/addons/test_mail/tests/test_mail_composer_mixin.py b/addons/test_mail/tests/test_mail_composer_mixin.py index 5b85c34ed5c..9591646b4a0 100644 --- a/addons/test_mail/tests/test_mail_composer_mixin.py +++ b/addons/test_mail/tests/test_mail_composer_mixin.py @@ -13,39 +13,101 @@ class TestMailComposerMixin(TestMailCommon, TestRecipients): def setUpClass(cls): super(TestMailComposerMixin, cls).setUpClass() - cls.mail_template = cls.env['mail.template'].create({ - 'subject': 'Subject for {{ object.name }}', - 'body_html': '

Body for

', + # ensure employee can create partners, necessary for templates + cls.user_employee.write({ + 'groups_id': [(4, cls.env.ref('base.group_partner_manager').id)], }) + cls.mail_template = cls.env['mail.template'].create({ + 'body_html': '

EnglishBody for

', + 'model_id': cls.env['ir.model']._get('mail.test.composer.source').id, + 'name': 'Test Template for mail.test.composer.source', + 'lang': '{{ object.customer_id.lang }}', + 'subject': 'EnglishSubject for {{ object.name }}', + }) + cls.test_record = cls.env['mail.test.composer.source'].create({ + 'name': cls.partner_1.name, + 'customer_id': cls.partner_1.id, + }) + + cls._activate_multi_lang( + layout_arch_db=' English Layout for ', + lang_code='es_ES', + test_record=cls.test_record, + test_template=cls.mail_template, + ) + @users("employee") def test_content_sync(self): - record = self.env['mail.test.composer.mixin'].create({ + """ Test updating template updates the dynamic fields accordingly. """ + source = self.test_record.with_env(self.env) + composer = self.env['mail.test.composer.mixin'].create({ 'name': 'Invite', 'template_id': self.mail_template.id, + 'source_ids': [(4, source.id)], }) - self.assertEqual(record.subject, self.mail_template.subject) - self.assertEqual(record.body, self.mail_template.body_html) + self.assertEqual(composer.body, self.mail_template.body_html) + self.assertEqual(composer.subject, self.mail_template.subject) + self.assertFalse(composer.lang, 'Fixme: lang is not propagated currently') - subject = record._render_field('subject', record.ids)[record.id] - self.assertEqual(subject, 'Subject for %s' % record.name) - body = record._render_field('body', record.ids)[record.id] - self.assertEqual(body, '

Body for %s

' % record.name) + subject = composer._render_field('subject', source.ids)[source.id] + self.assertEqual(subject, f'EnglishSubject for {source.name}') + body = composer._render_field('body', source.ids)[source.id] + self.assertEqual(body, f'

EnglishBody for {source.name}

') @users("employee") - def test_rendering(self): - record = self.env['mail.test.composer.mixin'].create({ - 'name': 'Invite', - 'subject': 'Subject for {{ object.name }}', - 'body': '

Content from

', + def test_rendering_custom(self): + """ Test rendering with custom strings (not coming from template) """ + source = self.test_record.with_env(self.env) + composer = self.env['mail.test.composer.mixin'].create({ 'description': '

Description for

', + 'body': '

SpecificBody from

', + 'name': 'Invite', + 'subject': 'SpecificSubject for {{ object.name }}', }) - self.assertEqual(record.subject, 'Subject for {{ object.name }}') - self.assertEqual(record.body, '

Content from

') + self.assertEqual(composer.body, '

SpecificBody from

') + self.assertEqual(composer.subject, 'SpecificSubject for {{ object.name }}') - subject = record._render_field('subject', record.ids)[record.id] - self.assertEqual(subject, 'Subject for %s' % record.name) - body = record._render_field('body', record.ids)[record.id] - self.assertEqual(body, '

Content from %s

' % self.env.user.name) - description = record._render_field('description', record.ids)[record.id] - self.assertEqual(description, '

Description for Invite

') + subject = composer._render_field('subject', source.ids)[source.id] + self.assertEqual(subject, f'SpecificSubject for {source.name}') + body = composer._render_field('body', source.ids)[source.id] + self.assertEqual(body, f'

SpecificBody from {self.env.user.name}

') + description = composer._render_field('description', source.ids)[source.id] + self.assertEqual(description, f'

Description for {source.name}

') + + @users("employee") + def test_rendering_lang(self): + """ Test rendering with language involved """ + template = self.mail_template.with_env(self.env) + customer = self.partner_1.with_env(self.env) + customer.lang = 'es_ES' + source = self.test_record.with_env(self.env) + composer = self.env['mail.test.composer.mixin'].create({ + 'description': '

Description for

', + 'lang': '{{ object.customer_id.lang }}', + 'name': 'Invite', + 'template_id': self.mail_template.id, + 'source_ids': [(4, source.id)], + }) + self.assertEqual(composer.body, template.body_html) + self.assertEqual(composer.subject, template.subject) + self.assertEqual(composer.lang, '{{ object.customer_id.lang }}') + + # do not specifically ask for language computation + subject = composer._render_field('subject', source.ids, compute_lang=False)[source.id] + self.assertEqual(subject, f'EnglishSubject for {source.name}') + body = composer._render_field('body', source.ids, compute_lang=False)[source.id] + self.assertEqual(body, f'

EnglishBody for {source.name}

') + description = composer._render_field('description', source.ids)[source.id] + self.assertEqual(description, f'

Description for {source.name}

') + + # ask for dynamic language computation + subject = composer._render_field('subject', source.ids, compute_lang=True)[source.id] + self.assertEqual(subject, f'EnglishSubject for {source.name}', + 'Fixme: translations are not done, as taking composer translations and not template one') + body = composer._render_field('body', source.ids, compute_lang=True)[source.id] + self.assertEqual(body, f'

EnglishBody for {source.name}

', + 'Fixme: translations are not done, as taking composer translations and not template one' + ) + description = composer._render_field('description', source.ids)[source.id] + self.assertEqual(description, f'

Description for {source.name}

') diff --git a/addons/test_mail/tests/test_mail_template.py b/addons/test_mail/tests/test_mail_template.py index fb1bec1977e..678df090b6e 100644 --- a/addons/test_mail/tests/test_mail_template.py +++ b/addons/test_mail/tests/test_mail_template.py @@ -128,7 +128,7 @@ class TestMailTemplateLanguages(TestMailTemplateCommon): mail_id = test_template.send_mail(test_record.id, email_layout_xmlid='mail.test_layout') mail = self.env['mail.mail'].sudo().browse(mail_id) self.assertEqual(mail.body_html, - '

SpanishBody for %s

Spanish Layout para Spanish description' % self.test_record.name) + '

SpanishBody for %s

Spanish Layout para Spanish Model Description' % self.test_record.name) self.assertEqual(mail.subject, 'SpanishSubject for %s' % self.test_record.name) @mute_logger('odoo.addons.mail.models.mail_mail') @@ -147,5 +147,5 @@ class TestMailTemplateLanguages(TestMailTemplateCommon): mail_id = test_template.send_mail(test_record.id, email_layout_xmlid='mail.test_layout') mail = self.env['mail.mail'].sudo().browse(mail_id) self.assertEqual(mail.body_html, - '

SpanishBody for %s

Spanish Layout para Spanish description' % self.test_record.name) + '

SpanishBody for %s

Spanish Layout para Spanish Model Description' % self.test_record.name) self.assertEqual(mail.subject, 'SpanishSubject for %s' % self.test_record.name) diff --git a/addons/test_mail/tests/test_message_post.py b/addons/test_mail/tests/test_message_post.py index 7341c9fd44a..b23052cc450 100644 --- a/addons/test_mail/tests/test_message_post.py +++ b/addons/test_mail/tests/test_message_post.py @@ -1210,7 +1210,49 @@ class TestMessagePostLang(TestMailCommon, TestRecipients): @users('employee') @mute_logger('odoo.addons.mail.models.mail_mail') - def test_composer_lang_template(self): + def test_composer_lang_template_comment(self): + test_record = self.test_records[0].with_user(self.env.user) + test_template = self.test_template.with_user(self.env.user) + + with self.mock_mail_gateway(): + test_record.message_post_with_template( + test_template.id, + composition_mode='comment', + email_layout_xmlid='mail.test_layout', + message_type='comment', + subtype_id=self.env.ref('mail.mt_comment').id, + ) + + record0_customer = self.env['res.partner'].search([('email_normalized', '=', 'test.record.1@test.customer.com')], limit=1) + self.assertTrue(record0_customer, 'Template usage should have created a contact based on record email') + + customer_email = self._find_sent_mail_wemail(record0_customer.email_formatted) + self.assertTrue(customer_email) + body = customer_email['body'] + # check content + self.assertIn(f'SpanishBody for {test_record.name}', body, + 'Body based on template should be translated') + # check subject + self.assertEqual(f'SpanishSubject for {test_record.name}', customer_email['subject'], + 'Subject based on template should be translated') + # check notification layout content + self.assertIn('Spanish Layout para', body, 'Layout content should be translated') + self.assertNotIn('English Layout for', body) + self.assertIn('Spanish Layout para Spanish Model Description', body, 'Model name should be translated') + # check notification layout strings + self.assertIn('View Lang Chatter Model', body, + 'Fixme: "View document" should be translated') + # self.assertIn('SpanishView Spanish Model Description', body, + # '"View document" should be translated') + # self.assertNotIn(f'View {test_record._description}', body, + # '"View document" should be translated') + # self.assertIn('SpanishButtonTitle', body, + # 'Groups-based action names should be translated') + self.assertIn('NotificationButtonTitle', body, 'Fixme: Groups-based action names should be translated') + + @users('employee') + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_composer_lang_template_mass(self): test_records = self.test_records.with_user(self.env.user) test_template = self.test_template.with_user(self.env.user) @@ -1231,11 +1273,15 @@ class TestMessagePostLang(TestMailCommon, TestRecipients): self.assertTrue(customer_email) body = customer_email['body'] # check content - # self.assertIn('SpanishBody for %s' % record.name, body, 'Body based on template should be translated') - self.assertIn('EnglishBody for %s' % record.name, body, 'Fixme: this should be translated') + # self.assertIn(f'SpanishBody for {record.name}', body, + # 'Body based on template should be translated') + self.assertIn(f'EnglishBody for {record.name}', body, + 'Fixme: Body based on template should be translated') # check subject - # self.assertEqual('SpanishSubject for %s' % record.name, customer_email['subject'], 'Subject based on template should be translated') - self.assertEqual('EnglishSubject for %s' % record.name, customer_email['subject'], 'Fixme: this should be translated') + # self.assertEqual(f'SpanishSubject for {record.name}', customer_email['subject'], + # 'Subject based on template should be translated') + self.assertEqual(f'EnglishSubject for {record.name}', customer_email['subject'], + 'Fixme: Subject based on template should be translated') @users('employee') @mute_logger('odoo.addons.mail.models.mail_mail') @@ -1255,16 +1301,20 @@ class TestMessagePostLang(TestMailCommon, TestRecipients): customer_email = self._find_sent_mail_wemail(self.partner_2.email_formatted) self.assertTrue(customer_email) body = customer_email['body'] - # check notification layout translation - self.assertIn('Spanish Layout para', body, 'Layout content should be translated') - self.assertNotIn('English Layout for', body) - self.assertIn('Spanish Layout para Spanish description', body, 'Model name should be translated') - self.assertIn('SpanishView Spanish description', body, '"View document" should be translated') - self.assertNotIn('View %s' % test_records[1]._description, body) - self.assertIn('TestSpanishStuff', body, 'Groups-based action names should be translated') - self.assertNotIn('TestStuff', body) # check content - self.assertIn('Hello', body, 'Body of posted message should be present') + self.assertIn('

Hello

', body, 'Body of posted message should be present') + # check notification layout content + self.assertIn('Spanish Layout para', body, + 'Layout content should be translated') + self.assertNotIn('English Layout for', body) + self.assertIn('Spanish Layout para Spanish Model Description', body, + 'Model name should be translated') + # check notification layout strings + self.assertIn('SpanishView Spanish Model Description', body, + '"View document" should be translated') + self.assertNotIn(f'View {test_records[1]._description}', body) + self.assertIn('SpanishButtonTitle', body, 'Groups-based action names should be translated') + self.assertNotIn('NotificationButtonTitle', body) @users('employee') @mute_logger('odoo.addons.mail.models.mail_mail') @@ -1288,15 +1338,23 @@ class TestMessagePostLang(TestMailCommon, TestRecipients): customer_email = self._find_sent_mail_wemail(customer.email_formatted) self.assertTrue(customer_email) body = customer_email['body'] - # check notification layout translation - self.assertIn('Spanish Layout para', body, 'Layout content should be translated') - self.assertNotIn('English Layout for', body) - self.assertIn('Spanish Layout para Spanish description', body, 'Model name should be translated') - # self.assertIn('SpanishView Spanish description', body, '"View document" should be translated') - self.assertIn('View %s' % test_records[1]._description, body, 'Fixme: this should be translated') - # self.assertIn('TestSpanishStuff', body, 'Groups-based action names should be translated') - self.assertIn('TestStuff', body, 'Fixme: groups-based action names should be translated') # check content - self.assertIn('SpanishBody for %s' % record.name, body, 'Body based on template should be translated') + self.assertIn(f'SpanishBody for {record.name}', body, + 'Body based on template should be translated') # check subject - self.assertEqual('SpanishSubject for %s' % record.name, customer_email['subject'], 'Subject based on template should be translated') + self.assertEqual(f'SpanishSubject for {record.name}', customer_email['subject'], + 'Subject based on template should be translated') + # check notification layout translation + self.assertIn('Spanish Layout para', body, + 'Layout content should be translated') + self.assertNotIn('English Layout for', body) + self.assertIn('Spanish Layout para Spanish Model Description', body, + 'Model name should be translated') + # self.assertIn('SpanishView Spanish Model Description', body, + # '"View document" should be translated') + self.assertIn(f'View {test_records[1]._description}', body, + 'Fixme: "View document" should be translated') + # self.assertIn('NotificationButtonTitle', body, + # 'Groups-based action names should be translated') + self.assertIn('NotificationButtonTitle', body, + 'Fixme: groups-based action names should be translated')