[MOV] (test_)mail(_full): redispatch some tests and split test mail models file

PURPOSE

Have a cleaner test_mail addons

SPECIFICATIONS

Keep only mail-related tests, move odoobot in test mail full, send "update
notification" tests in mail (specific to mail). Merge some test files to
lessen number of files, perform light file renaming.

Split test mail models file to prepare some cleaning in those models and tests.

LINKS

Prepares Task ID 2238597 (clean notification models)
Prepares Task ID 2083854 (improve mass mailing technical flows)
PR #49891
This commit is contained in:
Thibault Delavallée
2020-04-22 08:00:29 +00:00
parent 1b4767ee79
commit 6e347b196d
13 changed files with 222 additions and 211 deletions
+1
View File
@@ -2,3 +2,4 @@
from . import common
from . import test_res_partner
from . import test_update_notification
+3 -1
View File
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-
from . import test_mail_models
from . import test_mail_models
from . import test_mail_corner_case_models
from . import test_mail_thread_models
@@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class MailModel(models.Model):
_name = 'test_performance.mail'
_description = 'Test Performance Mail'
_inherit = 'mail.thread'
name = fields.Char()
value = fields.Integer()
value_pc = fields.Float(compute="_value_pc", store=True)
track = fields.Char(default='test', tracking=True)
partner_id = fields.Many2one('res.partner', string='Customer')
@api.depends('value')
def _value_pc(self):
for record in self:
record.value_pc = float(record.value) / 100
class MailTrackingModel(models.Model):
_description = 'Test Tracking Model'
_name = 'mail.test.tracking'
_inherit = ['mail.thread']
name = fields.Char(required=True, tracking=True)
field_0 = fields.Char(tracking=True)
field_1 = fields.Char(tracking=True)
field_2 = fields.Char(tracking=True)
class MailCompute(models.Model):
_name = 'mail.test.compute'
_description = "Test model with several tracked computed fields"
_inherit = ['mail.thread']
partner_id = fields.Many2one('res.partner', tracking=True)
partner_name = fields.Char(related='partner_id.name', store=True, tracking=True)
partner_email = fields.Char(related='partner_id.email', store=True, tracking=True)
partner_phone = fields.Char(related='partner_id.phone', tracking=True)
class MailMultiCompany(models.Model):
""" This model can be used in multi company tests"""
_name = 'mail.test.multi.company'
_description = "Test Multi Company Mail"
_inherit = 'mail.thread'
name = fields.Char()
company_id = fields.Many2one('res.company')
@@ -122,60 +122,3 @@ class MailTestAlias(models.Model):
values['alias_force_thread_id'] = self.id
values['alias_parent_thread_id'] = self.id
return values
class MailModel(models.Model):
_name = 'test_performance.mail'
_description = 'Test Performance Mail'
_inherit = 'mail.thread'
name = fields.Char()
value = fields.Integer()
value_pc = fields.Float(compute="_value_pc", store=True)
track = fields.Char(default='test', tracking=True)
partner_id = fields.Many2one('res.partner', string='Customer')
@api.depends('value')
def _value_pc(self):
for record in self:
record.value_pc = float(record.value) / 100
class MailCC(models.Model):
_name = 'mail.test.cc'
_description = "Test Email CC Thread"
_inherit = ['mail.thread.cc']
name = fields.Char()
class MailMultiCompany(models.Model):
""" This model can be used in multi company tests"""
_name = 'mail.test.multi.company'
_description = "Test Multi Company Mail"
_inherit = 'mail.thread'
name = fields.Char()
company_id = fields.Many2one('res.company')
class MailTrackingModel(models.Model):
_description = 'Test Tracking Model'
_name = 'mail.test.tracking'
_inherit = ['mail.thread']
name = fields.Char(required=True, tracking=True)
field_0 = fields.Char(tracking=True)
field_1 = fields.Char(tracking=True)
field_2 = fields.Char(tracking=True)
class MailCompute(models.Model):
_name = 'mail.test.compute'
_description = "Test model with several tracked computed fields"
_inherit = ['mail.thread']
partner_id = fields.Many2one('res.partner', tracking=True)
partner_name = fields.Char(related='partner_id.name', store=True, tracking=True)
partner_email = fields.Char(related='partner_id.email', store=True, tracking=True)
partner_phone = fields.Char(related='partner_id.phone', tracking=True)
@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class MailCC(models.Model):
_name = 'mail.test.cc'
_description = "Test Email CC Thread"
_inherit = ['mail.thread.cc']
name = fields.Char()
+1 -4
View File
@@ -2,19 +2,16 @@
from . import test_invite
from . import test_ir_actions
from . import test_discuss
from . import test_mail_activity
from . import test_mail_followers
from . import test_mail_message
from . import test_mail_mail
from . import test_mail_channel
from . import test_mail_gateway
from . import test_mail_redirect
from . import test_mail_template
from . import test_mail_thread_internals
from . import test_message_composer
from . import test_message_management
from . import test_message_post
from . import test_message_track
from . import test_odoobot
from . import test_performance
from . import test_update_notification
@@ -1,67 +0,0 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from werkzeug.urls import url_decode, url_parse
from odoo.tests.common import HttpCase, tagged
@tagged('-at_install', 'post_install')
class TestMultiCompany(HttpCase):
def test_redirect_to_records(self):
self.company_A = self.env['res.company'].create({
'name': 'Company A',
'user_ids': [(4, self.ref('base.user_admin'))],
})
self.company_B = self.env['res.company'].create({
'name': 'Company B',
})
self.multi_company_record = self.env['mail.test.multi.company'].create({
'name': 'Multi Company Record',
'company_id': self.company_A.id,
})
# Test Case 0
# Not logged, redirect to web/login
response = self.url_open('/mail/view?model=%s&res_id=%s' % (
self.multi_company_record._name,
self.multi_company_record.id), timeout=15)
path = url_parse(response.url).path
self.assertEqual(path, '/web/login')
self.authenticate('admin', 'admin')
# Test Case 1
# Logged into company 1, try accessing record in company A
# _redirect_to_record should add company A in allowed_company_ids
response = self.url_open('/mail/view?model=%s&res_id=%s' % (
self.multi_company_record._name,
self.multi_company_record.id), timeout=15)
self.assertEqual(response.status_code, 200)
fragment = url_parse(response.url).fragment
cids = url_decode(fragment)['cids']
self.assertEqual(cids, '1,%s' % (self.company_A.id))
# Test Case 2
# Logged into company 1, try accessing record in company B
# _redirect_to_record should redirect to messaging as the user
# doesn't have any access for this company
self.multi_company_record.company_id = self.company_B
response = self.url_open('/mail/view?model=%s&res_id=%s' % (
self.multi_company_record._name,
self.multi_company_record.id), timeout=15)
self.assertEqual(response.status_code, 200)
fragment = url_parse(response.url).fragment
action = url_decode(fragment)['action']
self.assertEqual(action, 'mail.action_discuss')
@@ -1,7 +1,10 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from werkzeug.urls import url_parse, url_decode
from odoo.addons.test_mail.tests.common import TestMailCommon, TestRecipients
from odoo.tests.common import tagged, HttpCase
from odoo.tools import mute_logger
@@ -141,3 +144,65 @@ class TestDiscuss(TestMailCommon, TestRecipients):
(False, 'cc1@example.com', 'CC Email'),
(False, 'cc2@example.com', 'CC Email'),
], 'cc should be in suggestions')
@tagged('-at_install', 'post_install')
class TestMultiCompany(HttpCase):
def test_redirect_to_records(self):
self.company_A = self.env['res.company'].create({
'name': 'Company A',
'user_ids': [(4, self.ref('base.user_admin'))],
})
self.company_B = self.env['res.company'].create({
'name': 'Company B',
})
self.multi_company_record = self.env['mail.test.multi.company'].create({
'name': 'Multi Company Record',
'company_id': self.company_A.id,
})
# Test Case 0
# Not logged, redirect to web/login
response = self.url_open('/mail/view?model=%s&res_id=%s' % (
self.multi_company_record._name,
self.multi_company_record.id), timeout=15)
path = url_parse(response.url).path
self.assertEqual(path, '/web/login')
self.authenticate('admin', 'admin')
# Test Case 1
# Logged into company 1, try accessing record in company A
# _redirect_to_record should add company A in allowed_company_ids
response = self.url_open('/mail/view?model=%s&res_id=%s' % (
self.multi_company_record._name,
self.multi_company_record.id), timeout=15)
self.assertEqual(response.status_code, 200)
fragment = url_parse(response.url).fragment
cids = url_decode(fragment)['cids']
self.assertEqual(cids, '1,%s' % (self.company_A.id))
# Test Case 2
# Logged into company 1, try accessing record in company B
# _redirect_to_record should redirect to messaging as the user
# doesn't have any access for this company
self.multi_company_record.company_id = self.company_B
response = self.url_open('/mail/view?model=%s&res_id=%s' % (
self.multi_company_record._name,
self.multi_company_record.id), timeout=15)
self.assertEqual(response.status_code, 200)
fragment = url_parse(response.url).fragment
action = url_decode(fragment)['action']
self.assertEqual(action, 'mail.action_discuss')
+60 -55
View File
@@ -4,8 +4,10 @@
from unittest.mock import patch
from odoo.addons.test_mail.tests.common import TestMailCommon
from odoo.tests.common import tagged
@tagged('mail_track')
class TestTracking(TestMailCommon):
def setUp(self):
@@ -127,61 +129,6 @@ class TestTracking(TestMailCommon):
# one email send due to template
self.assertSentEmail(self.record.env.user.partner_id, [self.partner_admin], body='<p>Hello Test</p>')
def test_message_tracking_sequence(self):
""" Update some tracked fields and check that the mail.tracking.value are ordered according to their tracking_sequence"""
self.record.write({
'name': 'Zboub',
'customer_id': self.user_admin.partner_id.id,
'user_id': self.user_admin.id,
'umbrella_id': self.env['mail.test'].with_context(mail_create_nosubscribe=True).create({'name': 'Umbrella'}).id
})
self.flush_tracking()
self.assertEqual(len(self.record.message_ids), 1, 'should have 1 tracking message')
tracking_values = self.env['mail.tracking.value'].search([('mail_message_id', '=', self.record.message_ids.id)])
self.assertEqual(tracking_values[0].tracking_sequence, 1)
self.assertEqual(tracking_values[1].tracking_sequence, 2)
self.assertEqual(tracking_values[2].tracking_sequence, 100)
def test_track_groups(self):
# patch the group attribute
field = self.record._fields['email_from']
self.addCleanup(setattr, field, 'groups', field.groups)
field.groups = 'base.group_erp_manager'
self.record.sudo().write({'email_from': 'X'})
self.flush_tracking()
msg_emp = self.record.message_ids.message_format()
msg_sudo = self.record.sudo().message_ids.message_format()
self.assertFalse(msg_emp[0].get('tracking_value_ids'), "should not have protected tracking values")
self.assertTrue(msg_sudo[0].get('tracking_value_ids'), "should have protected tracking values")
def test_notify_track_groups(self):
# patch the group attribute
field = self.record._fields['email_from']
self.addCleanup(setattr, field, 'groups', field.groups)
field.groups = 'base.group_erp_manager'
self.record.sudo().write({'email_from': 'X'})
self.flush_tracking()
msg_emp = self.record._notify_prepare_template_context(self.record.message_ids, {})
msg_sudo = self.record.sudo()._notify_prepare_template_context(self.record.message_ids, {})
self.assertFalse(msg_emp.get('tracking_values'), "should not have protected tracking values")
self.assertTrue(msg_sudo.get('tracking_values'), "should have protected tracking values")
def test_unlinked_field(self):
record_sudo = self.record.sudo()
record_sudo.write({'email_from': 'X'}) # create a tracking value
self.flush_tracking()
self.assertEqual(len(record_sudo.message_ids.tracking_value_ids), 1)
ir_model_field = self.env['ir.model.fields'].search([
('model', '=', 'mail.test.full'),
('name', '=', 'email_from')])
ir_model_field.with_context(_force_unlink=True).unlink()
self.assertEqual(len(record_sudo.message_ids.tracking_value_ids), 0)
def test_create_partner_from_tracking_multicompany(self):
company1 = self.env['res.company'].create({'name': 'company1'})
self.env.user.write({'company_ids': [(4, company1.id, False)]})
@@ -334,3 +281,61 @@ class TestTracking(TestMailCommon):
('partner_name', 'char', 'Fool', 'Bar'),
('partner_email', 'char', 'foo@example.com', 'bar@example.com'),
])
@tagged('mail_track')
class TestTrackingInternals(TestMailCommon):
def setUp(self):
super(TestTrackingInternals, self).setUp()
record = self.env['mail.test.full'].with_user(self.user_employee).with_context(self._test_context).create({
'name': 'Test',
})
self.flush_tracking()
self.record = record.with_context(mail_notrack=False)
def test_track_groups(self):
field = self.record._fields['email_from']
self.addCleanup(setattr, field, 'groups', field.groups)
field.groups = 'base.group_erp_manager'
self.record.sudo().write({'email_from': 'X'})
self.flush_tracking()
msg_emp = self.record.message_ids.message_format()
msg_sudo = self.record.sudo().message_ids.message_format()
self.assertFalse(msg_emp[0].get('tracking_value_ids'), "should not have protected tracking values")
self.assertTrue(msg_sudo[0].get('tracking_value_ids'), "should have protected tracking values")
msg_emp = self.record._notify_prepare_template_context(self.record.message_ids, {})
msg_sudo = self.record.sudo()._notify_prepare_template_context(self.record.message_ids, {})
self.assertFalse(msg_emp.get('tracking_values'), "should not have protected tracking values")
self.assertTrue(msg_sudo.get('tracking_values'), "should have protected tracking values")
def test_track_sequence(self):
""" Update some tracked fields and check that the mail.tracking.value are ordered according to their tracking_sequence"""
self.record.write({
'name': 'Zboub',
'customer_id': self.user_admin.partner_id.id,
'user_id': self.user_admin.id,
'umbrella_id': self.env['mail.test'].with_context(mail_create_nosubscribe=True).create({'name': 'Umbrella'}).id
})
self.flush_tracking()
self.assertEqual(len(self.record.message_ids), 1, 'should have 1 tracking message')
tracking_values = self.env['mail.tracking.value'].search([('mail_message_id', '=', self.record.message_ids.id)])
self.assertEqual(tracking_values[0].tracking_sequence, 1)
self.assertEqual(tracking_values[1].tracking_sequence, 2)
self.assertEqual(tracking_values[2].tracking_sequence, 100)
def test_unlinked_field(self):
record_sudo = self.record.sudo()
record_sudo.write({'email_from': 'new_value'}) # create a tracking value
self.flush_tracking()
self.assertEqual(len(record_sudo.message_ids.tracking_value_ids), 1)
ir_model_field = self.env['ir.model.fields'].search([
('model', '=', 'mail.test.full'),
('name', '=', 'email_from')])
ir_model_field.with_context(_force_unlink=True).unlink()
self.assertEqual(len(record_sudo.message_ids.tracking_value_ids), 0)
+26 -27
View File
@@ -183,6 +183,11 @@ class TestMailAPIPerformance(BaseMailPerformance):
'notification_type': 'inbox',
'groups_id': [(6, 0, [self.env.ref('base.group_user').id])],
})
# automatically follow activities, for backward compatibility concerning query count
self.env.ref('mail.mt_activities').write({'default': True})
def _create_test_records(self):
self.test_record_full = self.env['mail.test.full'].with_context(self._quick_create_ctx).create({
'name': 'TestRecord',
'customer_id': self.customer.id,
@@ -199,9 +204,6 @@ class TestMailAPIPerformance(BaseMailPerformance):
'email_to': '${("%s Customer <%s>" % (object.name, object.email_from)) | safe}',
})
# automatically follow activities, for backward compatibility concerning query count
self.env.ref('mail.mt_activities').write({'default': True})
@users('__system__', 'emp')
@warmup
def test_adv_activity(self):
@@ -255,6 +257,7 @@ class TestMailAPIPerformance(BaseMailPerformance):
@warmup
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail')
def test_mail_composer(self):
self._create_test_records()
test_record = self.env['mail.test.full'].browse(self.test_record_full.id)
customer_id = self.customer.id
with self.assertQueryCount(__system__=4, emp=4):
@@ -274,6 +277,7 @@ class TestMailAPIPerformance(BaseMailPerformance):
@warmup
@mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
def test_mail_composer_w_template(self):
self._create_test_records()
test_record = self.env['mail.test.full'].browse(self.test_record_full.id)
test_template = self.env['mail.template'].browse(self.test_template_full.id)
# TODO FIXME non deterministic, last check 25 Mar 2020. Runbot at most +7 compared to local.
@@ -395,6 +399,25 @@ class TestMailAPIPerformance(BaseMailPerformance):
with self.assertQueryCount(__system__=2, emp=2):
record.message_subscribe(partner_ids=self.user_test.partner_id.ids, subtype_ids=subtype_ids)
@mute_logger('odoo.models.unlink')
@users('__system__', 'emp')
@warmup
def test_message_track(self):
record = self.env['mail.test.tracking'].create({'name': 'Zizizatestname'})
with self.assertQueryCount(__system__=3, emp=3):
record.write({'name': 'Zizizanewtestname'})
record.flush()
with self.assertQueryCount(__system__=5, emp=5):
record.write({'field_%s' % (i): 'Tracked Char Fields %s' % (i) for i in range(3)})
record.flush()
with self.assertQueryCount(__system__=6, emp=6):
record.write({'field_%s' % (i): 'Field Without Cache %s' % (i) for i in range(3)})
record.flush()
record.write({'field_%s' % (i): 'Field With Cache %s' % (i) for i in range(3)})
record.flush()
@tagged('mail_performance')
class TestMailComplexPerformance(BaseMailPerformance):
@@ -949,27 +972,3 @@ class TestMailHeavyPerformancePost(BaseMailPerformance):
self.assertEqual(self.attachements.mapped('res_model'), [record._name for i in range(3)])
self.assertEqual(self.attachements.mapped('res_id'), [record.id for i in range(3)])
# self.assertEqual(record.message_ids[0].notified_partner_ids, [])
@tagged('mail_performance')
class TestTrackingPerformance(BaseMailPerformance):
@users('__system__', 'demo')
@warmup
def test_tracking_multiple_fields(self):
""" Check that tracking multiple fields is scalable """
record = self.env['mail.test.tracking'].create({'name': 'Zizizatestname'})
with self.assertQueryCount(__system__=3, demo=3):
record.write({'name': 'Zizizanewtestname'})
record.flush()
with self.assertQueryCount(__system__=5, demo=5):
record.write({'field_%s' % (i): 'Tracked Char Fields %s' % (i) for i in range(3)})
record.flush()
with self.assertQueryCount(__system__=6, demo=6):
record.write({'field_%s' % (i): 'Field Without Cache %s' % (i) for i in range(3)})
record.flush()
record.write({'field_%s' % (i): 'Field With Cache %s' % (i) for i in range(3)})
record.flush()
+1
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from . import common
from . import test_odoobot
from . import test_phone_blacklist
from . import test_mass_sms
from . import test_sms_composer