[IMP] (test_)mail: move and rewrite message tests related to channel or discuss

Purpose of this commit is to move moderation tests directly into mail channel
test file. That way it is easier to maintain or update them as they are
linked to that specific model and not global to mail.thread.

Also containing
  * remove unnecessary tests or merge tests belonging to the same category;
  * make tests more readable;

Followup of odoo/odoo@e9571a4
Followup of odoo/odoo@1fadb3ec5d

Task ID-2421795

closes odoo/odoo#64501

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Thibault Delavallée
2021-01-13 15:54:19 +00:00
parent ba0890ebb3
commit d1361d9e3a
3 changed files with 147 additions and 178 deletions
+95
View File
@@ -387,6 +387,101 @@ class TestChannelModeration(MailCommon):
self.assertEqual(channel.channel_last_seen_partner_ids.partner_id, self.partner_employee | self.partner_root)
self.assertEqual(channel.moderator_ids, self.user_employee)
@mute_logger('odoo.models.unlink')
def test_message_moderate_ok(self):
msg_c1_admin1 = self._add_messages(self.channel, 'Body11', author=self.partner_admin, moderation_status='pending_moderation')
msg_c1_admin2 = self._add_messages(self.channel, 'Body12', author=self.partner_admin, moderation_status='pending_moderation')
msg_c1_emplo2 = self._add_messages(self.channel, 'Body21', author=self.partner_employee_2, moderation_status='pending_moderation')
self._reset_bus()
self.assertFalse(msg_c1_admin1.channel_ids | msg_c1_admin2.channel_ids | msg_c1_emplo2.channel_ids)
# accept
msg_c1_admin1.with_user(self.user_employee)._moderate('accept')
self.assertEqual(msg_c1_admin1.channel_ids, self.channel)
self.assertEqual(msg_c1_admin1.moderation_status, 'accepted')
self.assertEqual(msg_c1_admin2.moderation_status, 'pending_moderation')
self.assertBusNotifications([(self.cr.dbname, 'mail.channel', self.channel.id)])
# allow
self._reset_bus()
(msg_c1_admin1 | msg_c1_emplo2).with_user(self.user_employee)._moderate('allow')
self.assertEqual(msg_c1_admin1.channel_ids, self.channel)
self.assertEqual(msg_c1_admin2.channel_ids, self.channel)
self.assertEqual(msg_c1_emplo2.channel_ids, self.channel)
self.assertEqual(msg_c1_admin1.moderation_status, 'accepted')
self.assertEqual(msg_c1_admin2.moderation_status, 'accepted')
self.assertEqual(msg_c1_emplo2.moderation_status, 'accepted')
self.assertBusNotifications([
(self.cr.dbname, 'mail.channel', self.channel.id),
(self.cr.dbname, 'mail.channel', self.channel.id)])
@mute_logger('odoo.models.unlink')
def test_message_moderate_reject(self):
msg_c1_admin1 = self._add_messages(self.channel, '<p>Body11</p>', author=self.partner_admin, moderation_status='pending_moderation')
msg_c1_admin2 = self._add_messages(self.channel, '<p>Body12</p>', author=self.partner_admin, moderation_status='pending_moderation')
msg_c1_emplo2 = self._add_messages(self.channel, '<p>Body21</p>', author=self.partner_employee_2, moderation_status='pending_moderation')
msg_c1_portal = self._add_messages(self.channel, '<p>Body12</p>', author=self.partner_portal, moderation_status='pending_moderation')
id2, id4 = msg_c1_admin2.id, msg_c1_portal.id # save ids because unlink will discard them
self.assertFalse(msg_c1_admin1.channel_ids | msg_c1_admin2.channel_ids | msg_c1_emplo2.channel_ids | msg_c1_portal.channel_ids)
# test reject: should also send a rejection email
with self.mock_mail_gateway():
(msg_c1_admin1 | msg_c1_emplo2).with_user(self.user_employee)._moderate('reject', title='RejectTitle', comment='RejectComment')
self.assertEqual(len(self._new_mails), 2)
self.assertMailMailWEmails([self.partner_admin.email_formatted, self.partner_employee_2.email_formatted], 'outgoing', 'RejectComment',
fields_values={'subject': 'RejectTitle', 'author_id': self.partner_employee})
self.assertTrue(all('RejectComment' in body for body in self._new_mails.mapped('body_html')))
self.assertTrue(all('Body' in body for body in self._new_mails.mapped('body_html')))
# test discard: silently remove
self._reset_bus()
(msg_c1_admin2 + msg_c1_portal).with_user(self.user_employee)._moderate_discard()
# check all generated bus notifications
self.assertBusNotifications(
[(self.cr.dbname, 'res.partner', self.partner_admin.id),
(self.cr.dbname, 'res.partner', self.partner_employee.id),
(self.cr.dbname, 'res.partner', self.partner_portal.id)],
[{'type': 'deletion', 'message_ids': [id2]}, # author of 1 message
{'type': 'deletion', 'message_ids': [id2, id4]}, # moderator
{'type': 'deletion', 'message_ids': [id4]}] # author of 1 message
)
@mute_logger('odoo.models.unlink')
def test_message_notify_moderators(self):
# create pending messages in another channel to have two notification to push
msg_c1_admin1 = self._add_messages(self.channel, '<p>Body11</p>', author=self.partner_admin, moderation_status='pending_moderation')
msg_c1_admin2 = self._add_messages(self.channel, '<p>Body12</p>', author=self.partner_admin, moderation_status='pending_moderation')
msg_c1_portal = self._add_messages(self.channel, '<p>Body21</p>', author=self.partner_employee_2, moderation_status='pending_moderation')
channel_2 = self.env['mail.channel'].create({
'name': 'Moderation_1',
'email_send': True,
'moderation': True,
'channel_partner_ids': [(4, self.partner_admin.id)],
'moderator_ids': [(4, self.user_admin.id)],
})
msg_c2_portal = self._add_messages(channel_2, 'Body31', author=self.partner_employee_2, moderation_status='pending_moderation')
# one notification for each moderator: employee (channel1), admin (channel2)
with self.assertPostNotifications([{
'content': 'Hello %s' % self.partner_employee.name,
'message_type': 'user_notification', 'subtype': 'mail.mt_note',
'notif': [{
'partner': self.partner_employee,
'type': 'inbox'}]
}, {
'content': 'Hello %s' % self.partner_admin.name,
'message_type': 'user_notification', 'subtype': 'mail.mt_note',
'notif': [{
'partner': self.partner_admin,
'type': 'inbox'}]
}]):
self.env['mail.message']._notify_moderators()
@users('employee')
def test_moderation_fields(self):
channel = self.env['mail.channel'].browse(self.channel.ids)
-177
View File
@@ -378,180 +378,3 @@ class TestMessageAccess(TestMailCommon):
self.message.write({'model': 'mail.channel', 'res_id': self.group_public.id, 'moderation_status': 'pending_moderation'})
with self.assertRaises(AccessError):
self.message.with_user(self.user_employee).write({'moderation_status': 'accepted'})
@mute_logger('openerp.addons.mail.models.mail_mail')
def test_mark_all_as_read(self):
self.user_employee.notification_type = 'inbox'
emp_partner = self.user_employee.partner_id.with_user(self.user_employee)
group_private = self.env['mail.channel'].with_context({
'mail_create_nolog': True,
'mail_create_nosubscribe': True,
'mail_channel_noautofollow': True,
}).create({
'name': 'Private',
'description': 'Private James R.',
'public': 'private',
'alias_name': 'private',
'alias_contact': 'followers'}
).with_context({'mail_create_nosubscribe': False})
# mark all as read clear needactions
msg1 = group_private.message_post(body='Test', message_type='comment', subtype_xmlid='mail.mt_comment', partner_ids=[emp_partner.id])
self._reset_bus()
emp_partner.env['mail.message'].mark_all_as_read(domain=[])
self.assertBusNotifications([(self.cr.dbname, 'res.partner', emp_partner.id)], [{ 'type': 'mark_as_read', 'message_ids': [msg1.id] }])
na_count = emp_partner.get_needaction_count()
self.assertEqual(na_count, 0, "mark all as read should conclude all needactions")
# mark all as read also clear inaccessible needactions
msg2 = group_private.message_post(body='Zest', message_type='comment', subtype_xmlid='mail.mt_comment', partner_ids=[emp_partner.id])
needaction_accessible = len(emp_partner.env['mail.message'].search([['needaction', '=', True]]))
self.assertEqual(needaction_accessible, 1, "a new message to a partner is readable to that partner")
msg2.sudo().partner_ids = self.env['res.partner']
emp_partner.env['mail.message'].search([['needaction', '=', True]])
needaction_length = len(emp_partner.env['mail.message'].search([['needaction', '=', True]]))
self.assertEqual(needaction_length, 1, "message should still be readable when notified")
na_count = emp_partner.get_needaction_count()
self.assertEqual(na_count, 1, "message not accessible is currently still counted")
self._reset_bus()
emp_partner.env['mail.message'].mark_all_as_read(domain=[])
self.assertBusNotifications([(self.cr.dbname, 'res.partner', emp_partner.id)], [{ 'type': 'mark_as_read', 'message_ids': [msg2.id] }])
na_count = emp_partner.get_needaction_count()
self.assertEqual(na_count, 0, "mark all read should conclude all needactions even inacessible ones")
@mute_logger('openerp.addons.mail.models.mail_mail')
def test_mark_all_as_read_share(self):
self.user_portal.notification_type = 'inbox'
portal_partner = self.user_portal.partner_id.with_user(self.user_portal)
# mark all as read clear needactions
self.group_pigs.message_post(body='Test', message_type='comment', subtype_xmlid='mail.mt_comment', partner_ids=[portal_partner.id])
portal_partner.env['mail.message'].mark_all_as_read(domain=[])
na_count = portal_partner.get_needaction_count()
self.assertEqual(na_count, 0, "mark all as read should conclude all needactions")
# mark all as read also clear inaccessible needactions
new_msg = self.group_pigs.message_post(body='Zest', message_type='comment', subtype_xmlid='mail.mt_comment', partner_ids=[portal_partner.id])
needaction_accessible = len(portal_partner.env['mail.message'].search([['needaction', '=', True]]))
self.assertEqual(needaction_accessible, 1, "a new message to a partner is readable to that partner")
new_msg.sudo().partner_ids = self.env['res.partner']
needaction_length = len(portal_partner.env['mail.message'].search([['needaction', '=', True]]))
self.assertEqual(needaction_length, 1, "message should still be readable when notified")
na_count = portal_partner.get_needaction_count()
self.assertEqual(na_count, 1, "message not accessible is currently still counted")
portal_partner.env['mail.message'].mark_all_as_read(domain=[])
na_count = portal_partner.get_needaction_count()
self.assertEqual(na_count, 0, "mark all read should conclude all needactions even inacessible ones")
@tagged('moderation')
class TestMessageModeration(TestMailCommon):
@classmethod
def setUpClass(cls):
super(TestMessageModeration, cls).setUpClass()
cls.channel_1 = cls.env['mail.channel'].create({
'name': 'Moderation_1',
'email_send': True,
'moderation': True
})
cls.user_employee.write({'moderation_channel_ids': [(6, 0, [cls.channel_1.id])]})
cls.user_portal = cls._create_portal_user()
# A pending moderation message needs to have field channel_ids empty. Moderators
# need to be able to notify a pending moderation message (in a channel they moderate).
cls.msg_c1_admin1 = cls._add_messages(cls.channel_1, 'Body11', author=cls.partner_admin, moderation_status='pending_moderation')
cls.msg_c1_admin2 = cls._add_messages(cls.channel_1, 'Body12', author=cls.partner_admin, moderation_status='pending_moderation')
cls.msg_c1_portal = cls._add_messages(cls.channel_1, 'Body21', author=cls.partner_portal, moderation_status='pending_moderation')
@mute_logger('odoo.models.unlink')
def test_moderate_accept(self):
self._reset_bus()
self.assertFalse(self.msg_c1_admin1.channel_ids | self.msg_c1_admin2.channel_ids | self.msg_c1_portal.channel_ids)
self.msg_c1_admin1.with_user(self.user_employee)._moderate('accept')
self.assertEqual(self.msg_c1_admin1.channel_ids, self.channel_1)
self.assertEqual(self.msg_c1_admin1.moderation_status, 'accepted')
self.assertEqual(self.msg_c1_admin2.moderation_status, 'pending_moderation')
self.assertBusNotifications([(self.cr.dbname, 'mail.channel', self.channel_1.id)])
@mute_logger('odoo.models.unlink')
def test_moderate_allow(self):
self._reset_bus()
self.msg_c1_admin1.with_user(self.user_employee)._moderate('allow')
self.assertEqual(self.msg_c1_admin1.channel_ids, self.channel_1)
self.assertEqual(self.msg_c1_admin2.channel_ids, self.channel_1)
self.assertEqual(self.msg_c1_admin1.moderation_status, 'accepted')
self.assertEqual(self.msg_c1_admin2.moderation_status, 'accepted')
self.assertBusNotifications([
(self.cr.dbname, 'mail.channel', self.channel_1.id),
(self.cr.dbname, 'mail.channel', self.channel_1.id)])
@mute_logger('odoo.models.unlink')
def test_moderate_reject(self):
with self.mock_mail_gateway():
(self.msg_c1_admin1 | self.msg_c1_portal).with_user(self.user_employee)._moderate_send_reject_email('Title', 'Message to author')
self.assertEqual(len(self._new_mails), 2)
for mail in self._new_mails:
self.assertEqual(mail.author_id, self.partner_employee)
self.assertEqual(mail.subject, 'Title')
self.assertEqual(mail.state, 'outgoing')
self.assertEqual(
set(self._new_mails.mapped('email_to')),
set([self.msg_c1_admin1.email_from, self.msg_c1_portal.email_from])
)
self.assertEqual(
set(self._new_mails.mapped('body_html')),
set(['<div>Message to author</div>\n%s\n' % self.msg_c1_admin1.body, '<div>Message to author</div>\n%s\n' % self.msg_c1_portal.body])
) # TDE note: \n are added by append content to html, because why not
@mute_logger('odoo.models.unlink')
def test_moderate_discard(self):
self._reset_bus()
id1, id2, id3 = self.msg_c1_admin1.id, self.msg_c1_admin2.id, self.msg_c1_portal.id # save ids because unlink will discard them
(self.msg_c1_admin1 | self.msg_c1_admin2 | self.msg_c1_portal).with_user(self.user_employee)._moderate_discard()
self.assertBusNotifications(
[(self.cr.dbname, 'res.partner', self.partner_admin.id),
(self.cr.dbname, 'res.partner', self.partner_employee.id),
(self.cr.dbname, 'res.partner', self.partner_portal.id)],
[{'type': 'deletion', 'message_ids': [id1, id2]}, # author of 2 messages
{'type': 'deletion', 'message_ids': [id1, id2, id3]}, # moderator
{'type': 'deletion', 'message_ids': [id3]}] # author of 1 message
)
@mute_logger('odoo.models.unlink')
def test_notify_moderators(self):
# create pending messages in another channel to have two notification to push
channel_2 = self.env['mail.channel'].create({
'name': 'Moderation_1',
'email_send': True,
'moderation': True
})
self.user_admin.write({'moderation_channel_ids': [(6, 0, [channel_2.id])]})
self.msg_c2_portal = self._add_messages(channel_2, 'Body31', author=self.partner_portal, moderation_status='pending_moderation')
# one notification for each moderator: employee (channel1), admin (channel2)
with self.assertPostNotifications([{
'content': 'Hello %s' % self.partner_employee.name,
'message_type': 'user_notification', 'subtype': 'mail.mt_note',
'notif': [{
'partner': self.partner_employee,
'type': 'inbox'}]
}, {
'content': 'Hello %s' % self.partner_admin.name,
'message_type': 'user_notification', 'subtype': 'mail.mt_note',
'notif': [{
'partner': self.partner_admin,
'type': 'inbox'}]
}]):
self.env['mail.message']._notify_moderators()
@@ -1,8 +1,12 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from unittest.mock import patch
from unittest.mock import DEFAULT
from werkzeug.urls import url_parse, url_decode
from odoo import exceptions
from odoo.addons.test_mail.models.test_mail_models import MailTestSimple
from odoo.addons.test_mail.tests.common import TestMailCommon, TestRecipients
from odoo.tests.common import tagged, HttpCase
from odoo.tools import mute_logger
@@ -107,7 +111,54 @@ class TestDiscuss(TestMailCommon, TestRecipients):
@classmethod
def setUpClass(cls):
super(TestDiscuss, cls).setUpClass()
cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({'name': 'Test', 'email_from': 'ignasse@example.com'})
cls.test_record = cls.env['mail.test.simple'].with_context(cls._test_context).create({
'name': 'Test',
'email_from': 'ignasse@example.com'
})
@mute_logger('openerp.addons.mail.models.mail_mail')
def test_mark_all_as_read(self):
def _employee_crash(*args, **kwargs):
""" If employee is test employee, consider he has no access on document """
recordset = args[0]
if recordset.env.uid == self.user_employee.id and not recordset.env.su:
if kwargs.get('raise_exception', True):
raise exceptions.AccessError('Hop hop hop Ernest, please step back.')
return False
return DEFAULT
with patch.object(MailTestSimple, 'check_access_rights', autospec=True, side_effect=_employee_crash):
with self.assertRaises(exceptions.AccessError):
self.env['mail.test.simple'].with_user(self.user_employee).browse(self.test_record.ids).read(['name'])
employee_partner = self.env['res.partner'].with_user(self.user_employee).browse(self.partner_employee.ids)
# mark all as read clear needactions
msg1 = self.test_record.message_post(body='Test', message_type='comment', subtype_xmlid='mail.mt_comment', partner_ids=[employee_partner.id])
self._reset_bus()
employee_partner.env['mail.message'].mark_all_as_read(domain=[])
self.assertBusNotifications([(self.cr.dbname, 'res.partner', employee_partner.id)], [{ 'type': 'mark_as_read', 'message_ids': [msg1.id] }])
na_count = employee_partner.get_needaction_count()
self.assertEqual(na_count, 0, "mark all as read should conclude all needactions")
# mark all as read also clear inaccessible needactions
msg2 = self.test_record.message_post(body='Zest', message_type='comment', subtype_xmlid='mail.mt_comment', partner_ids=[employee_partner.id])
needaction_accessible = len(employee_partner.env['mail.message'].search([['needaction', '=', True]]))
self.assertEqual(needaction_accessible, 1, "a new message to a partner is readable to that partner")
msg2.sudo().partner_ids = self.env['res.partner']
employee_partner.env['mail.message'].search([['needaction', '=', True]])
needaction_length = len(employee_partner.env['mail.message'].search([['needaction', '=', True]]))
self.assertEqual(needaction_length, 1, "message should still be readable when notified")
na_count = employee_partner.get_needaction_count()
self.assertEqual(na_count, 1, "message not accessible is currently still counted")
self._reset_bus()
employee_partner.env['mail.message'].mark_all_as_read(domain=[])
self.assertBusNotifications([(self.cr.dbname, 'res.partner', employee_partner.id)], [{ 'type': 'mark_as_read', 'message_ids': [msg2.id] }])
na_count = employee_partner.get_needaction_count()
self.assertEqual(na_count, 0, "mark all read should conclude all needactions even inacessible ones")
def test_set_message_done_user(self):
with self.assertSinglePostNotifications([{'partner': self.partner_employee, 'type': 'inbox'}], message_info={'content': 'Test'}):