Initial commit: Test packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:52 +02:00
commit 080accd21c
338 changed files with 32413 additions and 0 deletions

View file

@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import mail_test_access
from . import test_mail_corner_case_models
from . import test_mail_models
from . import test_mail_thread_models

View file

@ -0,0 +1,60 @@
from odoo import exceptions, fields, models
class MailTestAccess(models.Model):
""" Test access on mail models without depending on real models like channel
or partner which have their own set of ACLs. """
_description = 'Mail Access Test'
_name = 'mail.test.access'
_inherit = ['mail.thread.blacklist']
_mail_post_access = 'write' # default value but ease mock
_order = 'id DESC'
_primary_email = 'email_from'
name = fields.Char()
email_from = fields.Char()
phone = fields.Char()
customer_id = fields.Many2one('res.partner', 'Customer')
access = fields.Selection(
[
('public', 'public'),
('logged', 'Logged'),
('logged_ro', 'Logged readonly for portal'),
('followers', 'Followers'),
('internal', 'Internal'),
('internal_ro', 'Internal readonly'),
('admin', 'Admin'),
],
name='Access', default='public')
def _mail_get_partner_fields(self):
return ['customer_id']
class MailTestAccessCusto(models.Model):
""" Test access on mail models without depending on real models like channel
or partner which have their own set of ACLs. """
_description = 'Mail Access Test with Custo'
_name = 'mail.test.access.custo'
_inherit = ['mail.thread.blacklist']
_mail_post_access = 'write' # default value but ease mock
_order = 'id DESC'
_primary_email = 'email_from'
name = fields.Char()
email_from = fields.Char()
phone = fields.Char()
customer_id = fields.Many2one('res.partner', 'Customer')
is_locked = fields.Boolean()
def _mail_get_partner_fields(self):
return ['customer_id']
def _get_mail_message_access(self, res_ids, operation, model_name=None):
# customize message creation
if operation == "create":
if any(record.is_locked for record in self.browse(res_ids)):
raise exceptions.AccessError('Cannot post on locked records')
else:
return "read"
return super()._get_mail_message_access(res_ids, operation, model_name=model_name)

View file

@ -0,0 +1,183 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
class MailPerformanceThread(models.Model):
_name = 'mail.performance.thread'
_description = 'Performance: mail.thread'
_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 MailPerformanceTracking(models.Model):
_name = 'mail.performance.tracking'
_description = 'Performance: multi 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 MailTestFieldType(models.Model):
""" Test default values, notably type, messing through models during gateway
processing (i.e. lead.type versus attachment.type). """
_description = 'Test Field Type'
_name = 'mail.test.field.type'
_inherit = ['mail.thread']
name = fields.Char()
email_from = fields.Char()
datetime = fields.Datetime(default=fields.Datetime.now)
customer_id = fields.Many2one('res.partner', 'Customer')
type = fields.Selection([('first', 'First'), ('second', 'Second')])
user_id = fields.Many2one('res.users', 'Responsible', tracking=True)
@api.model_create_multi
def create(self, vals_list):
# Emulate an addon that alters the creation context, such as `crm`
if not self._context.get('default_type'):
self = self.with_context(default_type='first')
return super(MailTestFieldType, self).create(vals_list)
def _mail_get_partner_fields(self):
return ['customer_id']
class MailTestLang(models.Model):
""" A simple chatter model with lang-based capabilities, allowing to
test translations. """
_description = 'Lang Chatter Model'
_name = 'mail.test.lang'
_inherit = ['mail.thread']
name = fields.Char()
email_from = fields.Char()
customer_id = fields.Many2one('res.partner')
lang = fields.Char('Lang')
def _mail_get_partner_fields(self):
return ['customer_id']
def _notify_get_recipients_groups(self, msg_vals=None):
groups = super(MailTestLang, self)._notify_get_recipients_groups(msg_vals=msg_vals)
local_msg_vals = dict(msg_vals or {})
for group in [g for g in groups if g[0] in('follower', 'customer')]:
group_options = group[2]
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': _('NotificationButtonTitle')}
]
return groups
# ------------------------------------------------------------
# TRACKING MODELS
# ------------------------------------------------------------
class MailTestTrackCompute(models.Model):
_name = 'mail.test.track.compute'
_description = "Test tracking with 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 MailTestTrackMonetary(models.Model):
_name = 'mail.test.track.monetary'
_description = 'Test tracking monetary field'
_inherit = ['mail.thread']
company_id = fields.Many2one('res.company')
company_currency = fields.Many2one("res.currency", string='Currency', related='company_id.currency_id', readonly=True, tracking=True)
revenue = fields.Monetary('Revenue', currency_field='company_currency', tracking=True)
class MailTestMultiCompanyWithActivity(models.Model):
""" This model can be used in multi company tests with activity"""
_name = "mail.test.multi.company.with.activity"
_description = "Test Multi Company Mail With Activity"
_inherit = ["mail.thread", "mail.activity.mixin"]
name = fields.Char()
company_id = fields.Many2one("res.company")
class MailTestSelectionTracking(models.Model):
""" Test tracking for selection fields """
_description = 'Test Selection Tracking'
_name = 'mail.test.track.selection'
_inherit = ['mail.thread']
name = fields.Char()
selection_type = fields.Selection([('first', 'First'), ('second', 'Second')], tracking=True)
class MailTestTrackAll(models.Model):
_name = 'mail.test.track.all'
_description = 'Test tracking on all field types'
_inherit = ['mail.thread']
boolean_field = fields.Boolean('Boolean', tracking=True)
char_field = fields.Char('Char', tracking=True)
company_id = fields.Many2one('res.company')
currency_id = fields.Many2one('res.currency', related='company_id.currency_id')
date_field = fields.Date('Date', tracking=True)
datetime_field = fields.Datetime('Datetime', tracking=True)
float_field = fields.Float('Float', tracking=True)
html_field = fields.Html('Html', tracking=True)
integer_field = fields.Integer('Integer', tracking=True)
many2one_field_id = fields.Many2one('res.partner', string='Many2one', tracking=True)
monetary_field = fields.Monetary('Monetary', tracking=True)
selection_field = fields.Selection(string='Selection', selection=[['first', 'FIRST']], tracking=True)
text_field = fields.Text('Text', tracking=True)
# ------------------------------------------------------------
# OTHER
# ------------------------------------------------------------
class MailTestMultiCompany(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 MailTestMultiCompanyRead(models.Model):
""" Just mail.test.simple, but multi company and supporting posting
even if the user has no write access. """
_description = 'Simple Chatter Model '
_name = 'mail.test.multi.company.read'
_inherit = ['mail.test.multi.company']
_mail_post_access = 'read'
class MailTestNotMailThread(models.Model):
""" Models not inheriting from mail.thread but using some cross models
capabilities of mail. """
_name = 'mail.test.nothread'
_description = "NoThread Model"
name = fields.Char()
company_id = fields.Many2one('res.company')
customer_id = fields.Many2one('res.partner')

View file

@ -0,0 +1,330 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
class MailTestSimple(models.Model):
""" A very simple model only inheriting from mail.thread when only
communication history is necessary. """
_description = 'Simple Chatter Model'
_name = 'mail.test.simple'
_inherit = ['mail.thread']
name = fields.Char()
email_from = fields.Char()
class MailTestGateway(models.Model):
""" A very simple model only inheriting from mail.thread to test pure mass
mailing features and base performances. """
_description = 'Simple Chatter Model for Mail Gateway'
_name = 'mail.test.gateway'
_inherit = ['mail.thread.blacklist']
_primary_email = 'email_from'
name = fields.Char()
email_from = fields.Char()
custom_field = fields.Char()
@api.model
def message_new(self, msg_dict, custom_values=None):
""" Check override of 'message_new' allowing to update record values
base on incoming email. """
defaults = {
'email_from': msg_dict.get('from'),
}
defaults.update(custom_values or {})
return super().message_new(msg_dict, custom_values=defaults)
class MailTestGatewayGroups(models.Model):
""" A model looking like discussion channels / groups (flat thread and
alias). Used notably for advanced gatewxay tests. """
_description = 'Channel/Group-like Chatter Model for Mail Gateway'
_name = 'mail.test.gateway.groups'
_inherit = ['mail.thread.blacklist', 'mail.alias.mixin']
_mail_flat_thread = False
_primary_email = 'email_from'
name = fields.Char()
email_from = fields.Char()
custom_field = fields.Char()
customer_id = fields.Many2one('res.partner', 'Customer')
def _alias_get_creation_values(self):
values = super(MailTestGatewayGroups, self)._alias_get_creation_values()
values['alias_model_id'] = self.env['ir.model']._get('mail.test.gateway.groups').id
if self.id:
values['alias_force_thread_id'] = self.id
values['alias_parent_thread_id'] = self.id
return values
def _mail_get_partner_fields(self):
return ['customer_id']
def _message_get_default_recipients(self):
return dict(
(record.id, {
'email_cc': False,
'email_to': record.email_from if not record.customer_id.ids else False,
'partner_ids': record.customer_id.ids,
})
for record in self
)
class MailTestStandard(models.Model):
""" This model can be used in tests when automatic subscription and simple
tracking is necessary. Most features are present in a simple way. """
_description = 'Standard Chatter Model'
_name = 'mail.test.track'
_inherit = ['mail.thread']
name = fields.Char()
email_from = fields.Char()
user_id = fields.Many2one('res.users', 'Responsible', tracking=True)
container_id = fields.Many2one('mail.test.container', tracking=True)
company_id = fields.Many2one('res.company')
class MailTestActivity(models.Model):
""" This model can be used to test activities in addition to simple chatter
features. """
_description = 'Activity Model'
_name = 'mail.test.activity'
_inherit = ['mail.thread', 'mail.activity.mixin']
name = fields.Char()
date = fields.Date()
email_from = fields.Char()
active = fields.Boolean(default=True)
def action_start(self, action_summary):
return self.activity_schedule(
'test_mail.mail_act_test_todo',
summary=action_summary
)
def action_close(self, action_feedback, attachment_ids=None):
self.activity_feedback(['test_mail.mail_act_test_todo'],
feedback=action_feedback,
attachment_ids=attachment_ids)
class MailTestTicket(models.Model):
""" This model can be used in tests when complex chatter features are
required like modeling tasks or tickets. """
_description = 'Ticket-like model'
_name = 'mail.test.ticket'
_inherit = ['mail.thread']
_primary_email = 'email_from'
name = fields.Char()
email_from = fields.Char(tracking=True)
count = fields.Integer(default=1)
datetime = fields.Datetime(default=fields.Datetime.now)
mail_template = fields.Many2one('mail.template', 'Template')
customer_id = fields.Many2one('res.partner', 'Customer', tracking=2)
user_id = fields.Many2one('res.users', 'Responsible', tracking=1)
container_id = fields.Many2one('mail.test.container', tracking=True)
def _mail_get_partner_fields(self):
return ['customer_id']
def _message_get_default_recipients(self):
return dict(
(record.id, {
'email_cc': False,
'email_to': record.email_from if not record.customer_id.ids else False,
'partner_ids': record.customer_id.ids,
})
for record in self
)
def _notify_get_recipients_groups(self, msg_vals=None):
""" Activate more groups to test query counters notably (and be backward
compatible for tests). """
local_msg_vals = dict(msg_vals or {})
groups = super()._notify_get_recipients_groups(msg_vals=msg_vals)
for group_name, _group_method, group_data in groups:
if group_name == 'portal':
group_data['active'] = True
elif group_name == 'customer':
group_data['active'] = True
group_data['has_button_access'] = True
group_data['actions'] = [{
'url': self._notify_get_action_link(
'controller',
controller='/test_mail/do_stuff',
**local_msg_vals
),
'title': _('NotificationButtonTitle')
}]
return groups
def _track_template(self, changes):
res = super(MailTestTicket, self)._track_template(changes)
record = self[0]
if 'customer_id' in changes and record.mail_template:
res['customer_id'] = (record.mail_template, {'composition_mode': 'mass_mail'})
elif 'datetime' in changes:
res['datetime'] = ('test_mail.mail_test_ticket_tracking_view', {'composition_mode': 'mass_mail'})
return res
def _creation_subtype(self):
if self.container_id:
return self.env.ref('test_mail.st_mail_test_ticket_container_upd')
return super(MailTestTicket, self)._creation_subtype()
def _track_subtype(self, init_values):
self.ensure_one()
if 'container_id' in init_values and self.container_id:
return self.env.ref('test_mail.st_mail_test_ticket_container_upd')
return super(MailTestTicket, self)._track_subtype(init_values)
class MailTestTicketEL(models.Model):
""" Just mail.test.ticket, but exclusion-list enabled. Kept as different
model to avoid messing with existing tests, notably performance, and ease
backward comparison. """
_description = 'Ticket-like model with exclusion list'
_name = 'mail.test.ticket.el'
_inherit = [
'mail.test.ticket',
'mail.thread.blacklist',
]
_primary_email = 'email_from'
email_from = fields.Char(
'Email',
compute='_compute_email_from', readonly=False, store=True)
@api.depends('customer_id')
def _compute_email_from(self):
for ticket in self.filtered(lambda r: r.customer_id and not r.email_from):
ticket.email_from = ticket.customer_id.email_formatted
class MailTestTicketMC(models.Model):
""" Just mail.test.ticket, but multi company. Kept as different model to
avoid messing with existing tests, notably performance, and ease backward
comparison. """
_description = 'Ticket-like model'
_name = 'mail.test.ticket.mc'
_inherit = ['mail.test.ticket']
_primary_email = 'email_from'
company_id = fields.Many2one('res.company', 'Company', default=lambda self: self.env.company)
container_id = fields.Many2one('mail.test.container.mc', tracking=True)
def _creation_subtype(self):
if self.container_id:
return self.env.ref('test_mail.st_mail_test_ticket_container_mc_upd')
return super()._creation_subtype()
def _track_subtype(self, init_values):
self.ensure_one()
if 'container_id' in init_values and self.container_id:
return self.env.ref('test_mail.st_mail_test_ticket_container_mc_upd')
return super()._track_subtype(init_values)
class MailTestContainer(models.Model):
""" This model can be used in tests when container records like projects
or teams are required. """
_description = 'Project-like model with alias'
_name = 'mail.test.container'
_mail_post_access = 'read'
_inherit = ['mail.thread', 'mail.alias.mixin']
name = fields.Char()
description = fields.Text()
customer_id = fields.Many2one('res.partner', 'Customer')
alias_id = fields.Many2one(
'mail.alias', 'Alias',
delegate=True)
def _mail_get_partner_fields(self):
return ['customer_id']
def _message_get_default_recipients(self):
return dict(
(record.id, {
'email_cc': False,
'email_to': False,
'partner_ids': record.customer_id.ids,
})
for record in self
)
def _notify_get_recipients_groups(self, msg_vals=None):
""" Activate more groups to test query counters notably (and be backward
compatible for tests). """
groups = super(MailTestContainer, self)._notify_get_recipients_groups(msg_vals=msg_vals)
for group_name, _group_method, group_data in groups:
if group_name == 'portal':
group_data['active'] = True
return groups
def _alias_get_creation_values(self):
values = super(MailTestContainer, self)._alias_get_creation_values()
values['alias_model_id'] = self.env['ir.model']._get('mail.test.container').id
if self.id:
values['alias_force_thread_id'] = self.id
values['alias_parent_thread_id'] = self.id
return values
class MailTestContainerMC(models.Model):
""" Just mail.test.container, but multi company. Kept as different model to
avoid messing with existing tests, notably performance, and ease backward
comparison. """
_description = 'Project-like model with alias (MC)'
_name = 'mail.test.container.mc'
_mail_post_access = 'read'
_inherit = ['mail.test.container']
company_id = fields.Many2one('res.company', 'Company', default=lambda self: self.env.company)
class MailTestComposerMixin(models.Model):
""" A simple invite-like wizard using the composer mixin, rendering on
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']
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 = '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)
@api.depends('customer_id')
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
def _mail_get_partner_fields(self):
return ['customer_id']

View file

@ -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 MailTestCC(models.Model):
_name = 'mail.test.cc'
_description = "Test Email CC Thread"
_inherit = ['mail.thread.cc']
name = fields.Char()