[REF] mail: same_thread field changed into no_auto_thread, its contrary, to avoid...
[odoo/odoo.git] / addons / mail / tests / test_mail_message.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Business Applications
5 #    Copyright (c) 2012-TODAY OpenERP S.A. <http://openerp.com>
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 from openerp.addons.mail.tests.common import TestMail
23 from openerp.exceptions import AccessError
24 from openerp.osv.orm import except_orm
25 from openerp.tools import mute_logger
26
27
28 class TestMailMail(TestMail):
29
30     def test_00_partner_find_from_email(self):
31         """ Tests designed for partner fetch based on emails. """
32         cr, uid, user_raoul, group_pigs = self.cr, self.uid, self.user_raoul, self.group_pigs
33
34         # --------------------------------------------------
35         # Data creation
36         # --------------------------------------------------
37         # 1 - Partner ARaoul
38         p_a_id = self.res_partner.create(cr, uid, {'name': 'ARaoul', 'email': 'test@test.fr'})
39
40         # --------------------------------------------------
41         # CASE1: without object
42         # --------------------------------------------------
43
44         # Do: find partner with email -> first partner should be found
45         partner_info = self.mail_thread.message_partner_info_from_emails(cr, uid, None, ['Maybe Raoul <test@test.fr>'], link_mail=False)[0]
46         self.assertEqual(partner_info['full_name'], 'Maybe Raoul <test@test.fr>',
47                          'mail_thread: message_partner_info_from_emails did not handle email')
48         self.assertEqual(partner_info['partner_id'], p_a_id,
49                          'mail_thread: message_partner_info_from_emails wrong partner found')
50
51         # Data: add some data about partners
52         # 2 - User BRaoul
53         p_b_id = self.res_partner.create(cr, uid, {'name': 'BRaoul', 'email': 'test@test.fr', 'user_ids': [(4, user_raoul.id)]})
54
55         # Do: find partner with email -> first user should be found
56         partner_info = self.mail_thread.message_partner_info_from_emails(cr, uid, None, ['Maybe Raoul <test@test.fr>'], link_mail=False)[0]
57         self.assertEqual(partner_info['partner_id'], p_b_id,
58                          'mail_thread: message_partner_info_from_emails wrong partner found')
59
60         # --------------------------------------------------
61         # CASE1: with object
62         # --------------------------------------------------
63
64         # Do: find partner in group where there is a follower with the email -> should be taken
65         self.mail_group.message_subscribe(cr, uid, [group_pigs.id], [p_b_id])
66         partner_info = self.mail_group.message_partner_info_from_emails(cr, uid, group_pigs.id, ['Maybe Raoul <test@test.fr>'], link_mail=False)[0]
67         self.assertEqual(partner_info['partner_id'], p_b_id,
68                          'mail_thread: message_partner_info_from_emails wrong partner found')
69
70
71 class TestMailMessage(TestMail):
72
73     def test_00_mail_message_values(self):
74         """ Tests designed for testing email values based on mail.message, aliases, ... """
75         cr, uid, user_raoul_id = self.cr, self.uid, self.user_raoul_id
76
77         # Data: update + generic variables
78         reply_to1 = '_reply_to1@example.com'
79         reply_to2 = '_reply_to2@example.com'
80         email_from1 = 'from@example.com'
81         alias_domain = 'schlouby.fr'
82         raoul_from = 'Raoul Grosbedon <raoul@raoul.fr>'
83         raoul_from_alias = 'Raoul Grosbedon <raoul@schlouby.fr>'
84         raoul_reply_alias = '"YourCompany Pigs" <group+pigs@schlouby.fr>'
85
86         # --------------------------------------------------
87         # Case1: without alias_domain
88         # --------------------------------------------------
89         param_ids = self.registry('ir.config_parameter').search(cr, uid, [('key', '=', 'mail.catchall.domain')])
90         self.registry('ir.config_parameter').unlink(cr, uid, param_ids)
91
92         # Do: free message; specified values > default values
93         msg_id = self.mail_message.create(cr, user_raoul_id, {'no_auto_thread': True, 'reply_to': reply_to1, 'email_from': email_from1})
94         msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
95         # Test: message content
96         self.assertIn('reply_to', msg.message_id,
97                       'mail_message: message_id should be specific to a mail_message with a given reply_to')
98         self.assertEqual(msg.reply_to, reply_to1,
99                          'mail_message: incorrect reply_to: should come from values')
100         self.assertEqual(msg.email_from, email_from1,
101                          'mail_message: incorrect email_from: should come from values')
102
103         # Do: create a mail_mail with the previous mail_message + specified reply_to
104         mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel', 'reply_to': reply_to2})
105         mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
106         # Test: mail_mail content
107         self.assertEqual(mail.reply_to, reply_to2,
108                          'mail_mail: incorrect reply_to: should come from values')
109         self.assertEqual(mail.email_from, email_from1,
110                          'mail_mail: incorrect email_from: should come from mail.message')
111
112         # Do: mail_message attached to a document
113         msg_id = self.mail_message.create(cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_pigs_id})
114         msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
115         # Test: message content
116         self.assertIn('mail.group', msg.message_id,
117                       'mail_message: message_id should contain model')
118         self.assertIn('%s' % self.group_pigs_id, msg.message_id,
119                       'mail_message: message_id should contain res_id')
120         self.assertEqual(msg.reply_to, raoul_from,
121                          'mail_message: incorrect reply_to: should be Raoul')
122         self.assertEqual(msg.email_from, raoul_from,
123                          'mail_message: incorrect email_from: should be Raoul')
124
125         # --------------------------------------------------
126         # Case2: with alias_domain, without catchall alias
127         # --------------------------------------------------
128         self.registry('ir.config_parameter').set_param(cr, uid, 'mail.catchall.domain', alias_domain)
129         self.registry('ir.config_parameter').unlink(cr, uid, self.registry('ir.config_parameter').search(cr, uid, [('key', '=', 'mail.catchall.alias')]))
130
131         # Update message
132         msg_id = self.mail_message.create(cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_pigs_id})
133         msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
134         # Test: generated reply_to
135         self.assertEqual(msg.reply_to, raoul_reply_alias,
136                          'mail_mail: incorrect reply_to: should be Pigs alias')
137
138         # Update message: test alias on email_from
139         msg_id = self.mail_message.create(cr, user_raoul_id, {})
140         msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
141         # Test: generated reply_to
142         self.assertEqual(msg.reply_to, raoul_from_alias,
143                          'mail_mail: incorrect reply_to: should be message email_from using Raoul alias')
144
145         # --------------------------------------------------
146         # Case2: with alias_domain and  catchall alias
147         # --------------------------------------------------
148         self.registry('ir.config_parameter').set_param(self.cr, self.uid, 'mail.catchall.alias', 'gateway')
149
150         # Update message
151         msg_id = self.mail_message.create(cr, user_raoul_id, {})
152         msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
153         # Test: generated reply_to
154         self.assertEqual(msg.reply_to, '"YourCompany" <gateway@schlouby.fr>',
155                          'mail_mail: reply_to should equal the catchall email alias')
156
157         # Do: create a mail_mail
158         mail_id = self.mail_mail.create(cr, uid, {'state': 'cancel', 'reply_to': 'someone@example.com'})
159         mail = self.mail_mail.browse(cr, uid, mail_id)
160         # Test: mail_mail content
161         self.assertEqual(mail.reply_to, 'someone@example.com',
162                          'mail_mail: reply_to should equal the rpely_to given to create')
163
164     @mute_logger('openerp.addons.base.ir.ir_model', 'openerp.models')
165     def test_10_mail_message_search_access_rights(self):
166         """ Testing mail_message.search() using specific _search implementation """
167         cr, uid, group_pigs_id = self.cr, self.uid, self.group_pigs_id
168         # Data: comment subtype for mail.message creation
169         ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'mail', 'mt_comment')
170         subtype_id = ref and ref[1] or False
171
172         # Data: Birds group, private
173         group_birds_id = self.mail_group.create(self.cr, self.uid, {'name': 'Birds', 'public': 'private'})
174         # Data: Raoul is member of Pigs
175         self.mail_group.message_subscribe(cr, uid, [group_pigs_id], [self.partner_raoul_id])
176         # Data: various author_ids, partner_ids, documents
177         msg_id1 = self.mail_message.create(cr, uid, {'subject': '_Test', 'body': 'A', 'subtype_id': subtype_id})
178         msg_id2 = self.mail_message.create(cr, uid, {'subject': '_Test', 'body': 'A+B', 'partner_ids': [(6, 0, [self.partner_bert_id])], 'subtype_id': subtype_id})
179         msg_id3 = self.mail_message.create(cr, uid, {'subject': '_Test', 'body': 'A Pigs', 'model': 'mail.group', 'res_id': group_pigs_id, 'subtype_id': subtype_id})
180         msg_id4 = self.mail_message.create(cr, uid, {'subject': '_Test', 'body': 'A+B Pigs', 'model': 'mail.group', 'res_id': group_pigs_id, 'partner_ids': [(6, 0, [self.partner_bert_id])], 'subtype_id': subtype_id})
181         msg_id5 = self.mail_message.create(cr, uid, {'subject': '_Test', 'body': 'A+R Pigs', 'model': 'mail.group', 'res_id': group_pigs_id, 'partner_ids': [(6, 0, [self.partner_raoul_id])], 'subtype_id': subtype_id})
182         msg_id6 = self.mail_message.create(cr, uid, {'subject': '_Test', 'body': 'A Birds', 'model': 'mail.group', 'res_id': group_birds_id, 'subtype_id': subtype_id})
183         msg_id7 = self.mail_message.create(cr, self.user_raoul_id, {'subject': '_Test', 'body': 'B', 'subtype_id': subtype_id})
184         msg_id8 = self.mail_message.create(cr, self.user_raoul_id, {'subject': '_Test', 'body': 'B+R', 'partner_ids': [(6, 0, [self.partner_raoul_id])], 'subtype_id': subtype_id})
185
186         # Test: Bert: 2 messages that have Bert in partner_ids
187         msg_ids = self.mail_message.search(cr, self.user_bert_id, [('subject', 'like', '_Test')])
188         self.assertEqual(set([msg_id2, msg_id4]), set(msg_ids), 'mail_message search failed')
189         # Test: Raoul: 3 messages on Pigs Raoul can read (employee can read group with default values), 0 on Birds (private group)
190         msg_ids = self.mail_message.search(cr, self.user_raoul_id, [('subject', 'like', '_Test'), ('body', 'like', 'A')])
191         self.assertEqual(set([msg_id3, msg_id4, msg_id5]), set(msg_ids), 'mail_message search failed')
192         # Test: Raoul: 3 messages on Pigs Raoul can read (employee can read group with default values), 0 on Birds (private group) + 2 messages as author
193         msg_ids = self.mail_message.search(cr, self.user_raoul_id, [('subject', 'like', '_Test')])
194         self.assertEqual(set([msg_id3, msg_id4, msg_id5, msg_id7, msg_id8]), set(msg_ids), 'mail_message search failed')
195         # Test: Admin: all messages
196         msg_ids = self.mail_message.search(cr, uid, [('subject', 'like', '_Test')])
197         self.assertEqual(set([msg_id1, msg_id2, msg_id3, msg_id4, msg_id5, msg_id6, msg_id7, msg_id8]), set(msg_ids), 'mail_message search failed')
198
199     @mute_logger('openerp.addons.base.ir.ir_model', 'openerp.models')
200     def test_15_mail_message_check_access_rule(self):
201         """ Testing mail_message.check_access_rule() """
202         cr, uid = self.cr, self.uid
203         partner_bert_id, partner_raoul_id = self.partner_bert_id, self.partner_raoul_id
204         user_bert_id, user_raoul_id = self.user_bert_id, self.user_raoul_id
205
206         # Prepare groups: Pigs (employee), Jobs (public)
207         pigs_msg_id = self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Message')
208         priv_msg_id = self.mail_group.message_post(cr, uid, self.group_priv_id, body='Message')
209
210         # prepare an attachment
211         attachment_id = self.ir_attachment.create(cr, uid, {'datas': 'My attachment'.encode('base64'), 'name': 'doc.txt', 'datas_fname': 'doc.txt'})
212
213         # ----------------------------------------
214         # CASE1: read
215         # ----------------------------------------
216
217         # Do: create a new mail.message
218         message_id = self.mail_message.create(cr, uid, {'body': 'My Body', 'attachment_ids': [(4, attachment_id)]})
219
220         # Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc
221         with self.assertRaises(except_orm):
222             self.mail_message.read(cr, user_bert_id, message_id)
223         # Do: message is pushed to Bert
224         notif_id = self.mail_notification.create(cr, uid, {'message_id': message_id, 'partner_id': partner_bert_id})
225         # Test: Bert reads the message, ok because notification pushed
226         self.mail_message.read(cr, user_bert_id, message_id)
227         # Test: Bert downloads attachment, ok because he can read message
228         self.mail_message.download_attachment(cr, user_bert_id, message_id, attachment_id)
229         # Do: remove notification
230         self.mail_notification.unlink(cr, uid, notif_id)
231         # Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc
232         with self.assertRaises(except_orm):
233             self.mail_message.read(cr, self.user_bert_id, message_id)
234         # Test: Bert downloads attachment, crash because he can't read message
235         with self.assertRaises(except_orm):
236             self.mail_message.download_attachment(cr, user_bert_id, message_id, attachment_id)
237         # Do: Bert is now the author
238         self.mail_message.write(cr, uid, [message_id], {'author_id': partner_bert_id})
239         # Test: Bert reads the message, ok because Bert is the author
240         self.mail_message.read(cr, user_bert_id, message_id)
241         # Do: Bert is not the author anymore
242         self.mail_message.write(cr, uid, [message_id], {'author_id': partner_raoul_id})
243         # Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc
244         with self.assertRaises(except_orm):
245             self.mail_message.read(cr, user_bert_id, message_id)
246         # Do: message is attached to a document Bert can read, Jobs
247         self.mail_message.write(cr, uid, [message_id], {'model': 'mail.group', 'res_id': self.group_jobs_id})
248         # Test: Bert reads the message, ok because linked to a doc he is allowed to read
249         self.mail_message.read(cr, user_bert_id, message_id)
250         # Do: message is attached to a document Bert cannot read, Pigs
251         self.mail_message.write(cr, uid, [message_id], {'model': 'mail.group', 'res_id': self.group_pigs_id})
252         # Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc
253         with self.assertRaises(except_orm):
254             self.mail_message.read(cr, user_bert_id, message_id)
255
256         # ----------------------------------------
257         # CASE2: create
258         # ----------------------------------------
259
260         # Do: Bert creates a message on Pigs -> ko, no creation rights
261         with self.assertRaises(AccessError):
262             self.mail_message.create(cr, user_bert_id, {'model': 'mail.group', 'res_id': self.group_pigs_id, 'body': 'Test'})
263         # Do: Bert create a message on Jobs -> ko, no creation rights
264         with self.assertRaises(AccessError):
265             self.mail_message.create(cr, user_bert_id, {'model': 'mail.group', 'res_id': self.group_jobs_id, 'body': 'Test'})
266         # Do: Bert create a private message -> ko, no creation rights
267         with self.assertRaises(AccessError):
268             self.mail_message.create(cr, user_bert_id, {'body': 'Test'})
269
270         # Do: Raoul creates a message on Jobs -> ok, write access to the related document
271         self.mail_message.create(cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_jobs_id, 'body': 'Test'})
272         # Do: Raoul creates a message on Priv -> ko, no write access to the related document
273         with self.assertRaises(except_orm):
274             self.mail_message.create(cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_priv_id, 'body': 'Test'})
275         # Do: Raoul creates a private message -> ok
276         self.mail_message.create(cr, user_raoul_id, {'body': 'Test'})
277         # Do: Raoul creates a reply to a message on Priv -> ko
278         with self.assertRaises(except_orm):
279             self.mail_message.create(cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_priv_id, 'body': 'Test', 'parent_id': priv_msg_id})
280         # Do: Raoul creates a reply to a message on Priv-> ok if has received parent
281         self.mail_notification.create(cr, uid, {'message_id': priv_msg_id, 'partner_id': self.partner_raoul_id})
282         self.mail_message.create(cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_priv_id, 'body': 'Test', 'parent_id': priv_msg_id})
283
284     def test_20_message_set_star(self):
285         """ Tests for starring messages and its related access rights """
286         cr, uid = self.cr, self.uid
287         # Data: post a message on Pigs
288         msg_id = self.group_pigs.message_post(body='My Body', subject='1')
289         msg = self.mail_message.browse(cr, uid, msg_id)
290         msg_raoul = self.mail_message.browse(cr, self.user_raoul_id, msg_id)
291
292         # Do: Admin stars msg
293         self.mail_message.set_message_starred(cr, uid, [msg.id], True)
294         msg.refresh()
295         # Test: notification exists
296         notif_ids = self.mail_notification.search(cr, uid, [('partner_id', '=', self.partner_admin_id), ('message_id', '=', msg.id)])
297         self.assertEqual(len(notif_ids), 1, 'mail_message set_message_starred: more than one notification created')
298         # Test: notification starred
299         notif = self.mail_notification.browse(cr, uid, notif_ids[0])
300         self.assertTrue(notif.starred, 'mail_notification starred failed')
301         self.assertTrue(msg.starred, 'mail_message starred failed')
302
303         # Do: Raoul stars msg
304         self.mail_message.set_message_starred(cr, self.user_raoul_id, [msg.id], True)
305         msg_raoul.refresh()
306         # Test: notification exists
307         notif_ids = self.mail_notification.search(cr, uid, [('partner_id', '=', self.partner_raoul_id), ('message_id', '=', msg.id)])
308         self.assertEqual(len(notif_ids), 1, 'mail_message set_message_starred: more than one notification created')
309         # Test: notification starred
310         notif = self.mail_notification.browse(cr, uid, notif_ids[0])
311         self.assertTrue(notif.starred, 'mail_notification starred failed')
312         self.assertTrue(msg_raoul.starred, 'mail_message starred failed')
313
314         # Do: Admin unstars msg
315         self.mail_message.set_message_starred(cr, uid, [msg.id], False)
316         msg.refresh()
317         msg_raoul.refresh()
318         # Test: msg unstarred for Admin, starred for Raoul
319         self.assertFalse(msg.starred, 'mail_message starred failed')
320         self.assertTrue(msg_raoul.starred, 'mail_message starred failed')
321
322     def test_30_message_set_read(self):
323         """ Tests for reading messages and its related access rights """
324         cr, uid = self.cr, self.uid
325         # Data: post a message on Pigs
326         msg_id = self.group_pigs.message_post(body='My Body', subject='1')
327         msg = self.mail_message.browse(cr, uid, msg_id)
328         msg_raoul = self.mail_message.browse(cr, self.user_raoul_id, msg_id)
329
330         # Do: Admin reads msg
331         self.mail_message.set_message_read(cr, uid, [msg.id], True)
332         msg.refresh()
333         # Test: notification exists
334         notif_ids = self.mail_notification.search(cr, uid, [('partner_id', '=', self.partner_admin_id), ('message_id', '=', msg.id)])
335         self.assertEqual(len(notif_ids), 1, 'mail_message set_message_read: more than one notification created')
336         # Test: notification read
337         notif = self.mail_notification.browse(cr, uid, notif_ids[0])
338         self.assertTrue(notif['is_read'], 'mail_notification read failed')
339         self.assertFalse(msg.to_read, 'mail_message read failed')
340
341         # Do: Raoul reads msg
342         self.mail_message.set_message_read(cr, self.user_raoul_id, [msg.id], True)
343         msg_raoul.refresh()
344         # Test: notification exists
345         notif_ids = self.mail_notification.search(cr, uid, [('partner_id', '=', self.partner_raoul_id), ('message_id', '=', msg.id)])
346         self.assertEqual(len(notif_ids), 1, 'mail_message set_message_read: more than one notification created')
347         # Test: notification read
348         notif = self.mail_notification.browse(cr, uid, notif_ids[0])
349         self.assertTrue(notif['is_read'], 'mail_notification starred failed')
350         self.assertFalse(msg_raoul.to_read, 'mail_message starred failed')
351
352         # Do: Admin unreads msg
353         self.mail_message.set_message_read(cr, uid, [msg.id], False)
354         msg.refresh()
355         msg_raoul.refresh()
356         # Test: msg unread for Admin, read for Raoul
357         self.assertTrue(msg.to_read, 'mail_message read failed')
358         self.assertFalse(msg_raoul.to_read, 'mail_message read failed')
359
360     def test_40_message_vote(self):
361         """ Test designed for the vote/unvote feature. """
362         cr, uid = self.cr, self.uid
363         # Data: post a message on Pigs
364         msg_id = self.group_pigs.message_post(body='My Body', subject='1')
365         msg = self.mail_message.browse(cr, uid, msg_id)
366         msg_raoul = self.mail_message.browse(cr, self.user_raoul_id, msg_id)
367
368         # Do: Admin vote for msg
369         self.mail_message.vote_toggle(cr, uid, [msg.id])
370         msg.refresh()
371         # Test: msg has Admin as voter
372         self.assertEqual(set(msg.vote_user_ids), set([self.user_admin]), 'mail_message vote: after voting, Admin should be in the voter')
373         # Do: Bert vote for msg
374         self.mail_message.vote_toggle(cr, self.user_raoul_id, [msg.id])
375         msg_raoul.refresh()
376         # Test: msg has Admin and Bert as voters
377         self.assertEqual(set(msg_raoul.vote_user_ids), set([self.user_admin, self.user_raoul]), 'mail_message vote: after voting, Admin and Bert should be in the voters')
378         # Do: Admin unvote for msg
379         self.mail_message.vote_toggle(cr, uid, [msg.id])
380         msg.refresh()
381         msg_raoul.refresh()
382         # Test: msg has Bert as voter
383         self.assertEqual(set(msg.vote_user_ids), set([self.user_raoul]), 'mail_message vote: after unvoting, Bert should be in the voter')
384         self.assertEqual(set(msg_raoul.vote_user_ids), set([self.user_raoul]), 'mail_message vote: after unvoting, Bert should be in the voter')
385
386     @mute_logger('openerp.addons.base.ir.ir_model', 'openerp.models')
387     def test_50_mail_flow_access_rights(self):
388         """ Test a Chatter-looks alike flow to test access rights """
389         cr, uid = self.cr, self.uid
390         mail_compose = self.registry('mail.compose.message')
391         partner_bert_id, partner_raoul_id = self.partner_bert_id, self.partner_raoul_id
392         user_bert_id, user_raoul_id = self.user_bert_id, self.user_raoul_id
393
394         # Prepare groups: Pigs (employee), Jobs (public)
395         pigs_msg_id = self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Message', partner_ids=[self.partner_admin_id])
396         jobs_msg_id = self.mail_group.message_post(cr, uid, self.group_jobs_id, body='Message', partner_ids=[self.partner_admin_id])
397
398         # ----------------------------------------
399         # CASE1: Bert, without groups
400         # ----------------------------------------
401
402         # Do: Bert reads Jobs basic fields, ok because public = read access on the group
403         self.mail_group.read(cr, user_bert_id, [self.group_jobs_id], ['name', 'description'])
404         # Do: Bert reads Jobs messages, ok because read access on the group => read access on its messages
405         jobs_message_ids = self.mail_group.read(cr, user_bert_id, [self.group_jobs_id], ['message_ids'])[0]['message_ids']
406         self.mail_message.read(cr, user_bert_id, jobs_message_ids)
407         # Do: Bert browses Jobs, ok (no direct browse of partners), ok for messages, ko for followers (accessible to employees or partner manager)
408         bert_jobs = self.mail_group.browse(cr, user_bert_id, self.group_jobs_id)
409         trigger_read = bert_jobs.name
410         for message in bert_jobs.message_ids:
411             trigger_read = message.subject
412         for partner in bert_jobs.message_follower_ids:
413             with self.assertRaises(AccessError):
414                 trigger_read = partner.name
415         # Do: Bert comments Jobs, ko because no creation right
416         with self.assertRaises(AccessError):
417             self.mail_group.message_post(cr, user_bert_id, self.group_jobs_id, body='I love Pigs')
418
419         # Do: Bert writes on its own profile, ko because no message create access
420         with self.assertRaises(AccessError):
421             self.res_users.message_post(cr, user_bert_id, user_bert_id, body='I love Bert')
422             self.res_partner.message_post(cr, user_bert_id, partner_bert_id, body='I love Bert')
423
424         # ----------------------------------------
425         # CASE2: Raoul, employee
426         # ----------------------------------------
427
428         # Do: Raoul browses Jobs -> ok, ok for message_ids, of for message_follower_ids
429         raoul_jobs = self.mail_group.browse(cr, user_raoul_id, self.group_jobs_id)
430         trigger_read = raoul_jobs.name
431         for message in raoul_jobs.message_ids:
432             trigger_read = message.subject
433         for partner in raoul_jobs.message_follower_ids:
434             trigger_read = partner.name
435
436         # Do: Raoul comments Jobs, ok
437         self.mail_group.message_post(cr, user_raoul_id, self.group_jobs_id, body='I love Pigs')
438         # Do: Raoul create a mail.compose.message record on Jobs, because he uses the wizard
439         compose_id = mail_compose.create(cr, user_raoul_id,
440             {'subject': 'Subject', 'body': 'Body text', 'partner_ids': []},
441             {'default_composition_mode': 'comment', 'default_model': 'mail.group', 'default_res_id': self.group_jobs_id})
442         mail_compose.send_mail(cr, user_raoul_id, [compose_id])
443         # Do: Raoul replies to a Jobs message using the composer
444         compose_id = mail_compose.create(cr, user_raoul_id,
445             {'subject': 'Subject', 'body': 'Body text'},
446             {'default_composition_mode': 'comment', 'default_parent_id': pigs_msg_id})
447         mail_compose.send_mail(cr, user_raoul_id, [compose_id])