19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:32:39 +01:00
parent 38c6088dcc
commit d9452d2060
243 changed files with 30797 additions and 10815 deletions

View file

@ -1,4 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_avatar_card_tour
from . import test_livechat_hr_holidays
from . import test_im_livechat_portal
from . import test_performance
from . import test_performance_inbox
from . import test_livechat_session_open
from . import test_res_partner

View file

@ -0,0 +1,138 @@
from datetime import date, timedelta
from odoo import Command
from odoo.tests import tagged, users
from odoo.tests.common import HttpCase, new_test_user
from odoo.addons.mail.tests.common import MailCommon
@tagged("post_install", "-at_install")
class TestAvatarCardTour(MailCommon, HttpCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
new_test_user(
cls.env,
login="hr_user",
company_ids=[Command.link(cls.env.company.id), Command.link(cls.company_2.id)],
groups="hr.group_hr_user",
)
# hr setup for multi-company
department = (
cls.env["hr.department"]
.with_company(cls.company_2)
.create({"name": "Test Department", "company_id": cls.company_2.id})
)
job = (
cls.env["hr.job"]
.with_company(cls.company_2)
.create({"name": "Test Job Title", "company_id": cls.company_2.id})
)
other_partner = (
cls.env["res.partner"]
.with_company(cls.company_2)
.create({
"name": "Test Other Partner",
"company_id": cls.company_2.id,
"phone": "987654321",
})
)
test_employee = (
cls.env["hr.employee"]
.with_company(cls.company_2)
.create({
"name": "Test Employee",
"user_id": cls.user_employee_c2.id,
"company_id": cls.company_2.id,
"department_id": department.id,
"job_id": job.id,
"address_id": other_partner.id,
"work_email": "test_employee@test.com",
"work_phone": "123456789",
})
)
cls.test_employee = test_employee
cls.user_employee_c2.write({"employee_ids": [Command.link(test_employee.id)]})
new_test_user(
cls.env,
login="base_user",
company_ids=[Command.link(cls.env.company.id), Command.link(cls.company_2.id)],
)
# hr_holidays setup for multi-company
leave_type = (
cls.env["hr.leave.type"]
.with_company(cls.company_2)
.create(
{
"name": "Time Off multi company",
"company_id": cls.company_2.id,
"time_type": "leave",
"requires_allocation": False,
}
)
)
cls.env["hr.leave"].with_company(cls.company_2).with_context(
leave_skip_state_check=True
).create(
{
"name": "Test Leave",
"company_id": cls.company_2.id,
"holiday_status_id": leave_type.id,
"employee_id": cls.test_employee.id,
"request_date_from": (date.today() - timedelta(days=1)),
"request_date_to": (date.today() + timedelta(days=1)),
"state": "validate",
}
)
cls.test_record = cls.env["hr.department"].create(
[
{"name": "Test", "company_id": cls.env.company.id},
{"name": "Test 2", "company_id": cls.env.company.id},
{"name": "Test 3", "company_id": cls.company_2.id},
]
)
def _setup_channel(self, user):
self.user_employee_c2.partner_id.sudo().with_user(self.user_employee_c2).message_post(
body="Test message in chatter",
message_type="comment",
subtype_xmlid="mail.mt_comment",
)
activity_type_todo = "mail.mail_activity_data_todo"
self.test_record[0].activity_schedule(
activity_type_todo,
summary="Test Activity for Company 2",
user_id=user.id,
)
self.test_record[1].activity_schedule(
activity_type_todo,
summary="Another Test Activity for Company 2",
user_id=user.id,
)
self.test_record[2].activity_schedule(
activity_type_todo,
summary="Test Activity for Company 3",
user_id=user.id,
)
@users("admin", "hr_user")
def test_avatar_card_tour_multi_company(self):
# Clear existing activities to avoid interference with the test
self.env["mail.activity"].with_user(self.env.user).search([]).unlink()
self._setup_channel(self.env.user)
self.start_tour(
f"/odoo/res.partner/{self.user_employee_c2.partner_id.id}",
"avatar_card_tour",
login=self.env.user.login,
)
@users("base_user")
def test_avatar_card_tour_multi_company_no_hr_access(self):
self._setup_channel(self.env.user)
self.start_tour(
f"/odoo/res.partner/{self.user_employee_c2.partner_id.id}",
"avatar_card_tour_no_hr_access",
login=self.env.user.login,
)

View file

@ -0,0 +1,52 @@
from odoo import Command, tests
from odoo.addons.website_livechat.tests.test_chatbot_ui import TestLivechatChatbotUI
@tests.common.tagged("post_install", "-at_install")
class TestImLivechatPortal(TestLivechatChatbotUI):
def test_chatbot_redirect_to_portal(self):
project = self.env["project.project"].create({"name": "Portal Project"})
task = self.env["project.task"].create(
{"name": "Test Task Name Match", "project_id": project.id}
)
chatbot_redirect_script = self.env["chatbot.script"].create({"title": "Redirection Bot"})
question_step = self.env["chatbot.script.step"].create(
[
{
"chatbot_script_id": chatbot_redirect_script.id,
"message": "Hello, were do you want to go?",
"step_type": "question_selection",
},
{
"chatbot_script_id": chatbot_redirect_script.id,
"message": "Tadam, we are on the page you asked for!",
"step_type": "text",
},
]
)[0]
self.env["chatbot.script.answer"].create(
[
{
"name": "Go to the portal page",
"redirect_link": f"/my/tasks/{task.id}?access_token={task.access_token}",
"script_step_id": question_step.id,
},
]
)
livechat_channel = self.env["im_livechat.channel"].create(
{
"name": "Redirection Channel",
"rule_ids": [
Command.create(
{
"regex_url": "/",
"chatbot_script_id": chatbot_redirect_script.id,
}
)
],
}
)
default_website = self.env.ref("website.default_website")
default_website.channel_id = livechat_channel.id
self.env.ref("website.default_website").channel_id = livechat_channel.id
self.start_tour("/contactus", "chatbot_redirect_to_portal")

View file

@ -0,0 +1,52 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from dateutil.relativedelta import relativedelta
from odoo import Command, fields
from odoo.tests.common import HttpCase, tagged
from odoo.addons.mail.tests.common import MailCommon
@tagged("post_install", "-at_install")
class TestLivechatHrHolidays(HttpCase, MailCommon):
"""Tests for bridge between im_livechat and hr_holidays modules."""
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env["mail.presence"]._update_presence(cls.user_employee)
leave_type = cls.env["hr.leave.type"].create(
{"name": "Legal Leaves", "requires_allocation": False, "time_type": "leave"}
)
employee = cls.env["hr.employee"].create({"user_id": cls.user_employee.id})
cls.env["hr.leave"].with_context(leave_skip_state_check=True).create(
{
"employee_id": employee.id,
"holiday_status_id": leave_type.id,
"request_date_from": fields.Datetime.today() + relativedelta(days=-2),
"request_date_to": fields.Datetime.today() + relativedelta(days=2),
"state": "validate",
}
)
def test_operator_available_on_leave(self):
"""Test operator is available on leave when they are online."""
livechat_channel = self.env["im_livechat.channel"].create(
{"name": "support", "user_ids": [Command.link(self.user_employee.id)]}
)
self.assertEqual(self.user_employee.im_status, "leave_online")
self.assertEqual(livechat_channel.available_operator_ids, self.user_employee)
def test_operator_limit_on_leave(self):
"""Test livechat limit is correctly applied when operator is on leave and online."""
livechat_channel = self.env["im_livechat.channel"].create(
{
"max_sessions_mode": "limited",
"max_sessions": 1,
"name": "support",
"user_ids": [Command.link(self.user_employee.id)],
}
)
self.make_jsonrpc_request("/im_livechat/get_session", {"channel_id": livechat_channel.id})
self.assertEqual(self.user_employee.im_status, "leave_online")
self.assertFalse(livechat_channel.available_operator_ids)

View file

@ -0,0 +1,21 @@
import odoo
from odoo.addons.im_livechat.tests.common import TestImLivechatCommon
from odoo.tests import new_test_user
@odoo.tests.tagged("-at_install", "post_install")
class TestImLivechatSessions(TestImLivechatCommon):
def test_livechat_session_open(self):
new_test_user(
self.env,
login="operator",
groups="base.group_user,im_livechat.im_livechat_group_manager",
)
self.make_jsonrpc_request(
"/im_livechat/get_session", {"channel_id": self.livechat_channel.id}
)
action = self.env.ref("im_livechat.discuss_channel_action_from_livechat_channel")
self.start_tour(
f"/odoo/livechat/{self.livechat_channel.id}/action-{action.id}", "im_livechat_session_open",
login="operator"
)

View file

@ -0,0 +1,82 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from itertools import chain
from odoo.addons.mail.tests.common import MailCommon
from odoo.tests.common import HttpCase, tagged, warmup
@tagged("post_install", "-at_install", "is_query_count")
class TestInboxPerformance(HttpCase, MailCommon):
@warmup
def test_fetch_with_rating_stats_enabled(self):
"""
Computation of rating_stats should run a single query per model with rating_stats enabled.
"""
# Queries (in order):
# - search website (get_current_website by domain)
# - search website (get_current_website default)
# - search website_rewrite (_get_rewrites) sometimes occurs depending on the routing cache
# - insert res_device_log
# - _xmlid_lookup (_get_public_users)
# - fetch website (_get_cached_values)
# - get_param ir_config_parameter (_pre_dispatch website_sale)
# 4 _message_fetch:
# 2 _search_needaction:
# - fetch res_users (current user)
# - search ir_rule (_get_rules for mail.notification)
# - search ir_rule (_get_rules)
# - search mail_message
# 30 message _to_store:
# - search mail_message_schedule
# - fetch mail_message
# - search mail_followers
# 2 thread _to_store:
# - fetch slide_channel
# - fetch product_template
# - search mail_message_res_partner_starred_rel (_compute_starred)
# - search message_attachment_rel
# - search mail_link_preview
# - search mail_message_reaction
# - search mail_message_res_partner_rel
# - fetch mail_message_subtype
# - search mail_notification
# 7 _filtered_for_web_client:
# - fetch mail_notification
# 4 _compute_domain:
# - search ir_rule (_get_rules for res.partner)
# - search res_groups_users_rel
# - search rule_group_rel
# - fetch ir_rule
# - fetch res_company
# - fetch res_partner
# 2 _compute_rating_id:
# - search rating_rating
# - fetch rating_rating
# - search mail_tracking_value
# 3 _author_to_store:
# - fetch res_partner
# - search res_users
# - fetch res_users
# - search ir_rule (_get_rules for rating.rating)
# - read group rating_rating (_rating_get_stats_per_record for slide.channel)
# - read group rating_rating (_compute_rating_stats for slide.channel)
# - read group rating_rating (_rating_get_stats_per_record for product.template)
# - read group rating_rating (_compute_rating_stats for product.template)
# - get_param ir_config_parameter (_save_session)
first_model_records = self.env["product.template"].create(
[{"name": "Product A1"}, {"name": "Product A2"}]
)
second_model_records = self.env["slide.channel"].create(
[{"name": "Course B1"}, {"name": "Course B2"}]
)
for record in chain(first_model_records, second_model_records):
record.message_post(
body=f"<p>Test message for {record.name}</p>",
message_type="comment",
partner_ids=[self.user_employee.partner_id.id],
rating_value="4",
)
self.authenticate(self.user_employee.login, self.user_employee.password)
with self.assertQueryCount(43):
self.make_jsonrpc_request("/mail/inbox/messages")

View file

@ -0,0 +1,12 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.mail.tests.common import mail_new_test_user
from odoo.addons.mail.tests.common import MailCommon
from odoo.addons.mail.tools.discuss import Store
class TestResPartner(MailCommon):
def test_portal_user_store_data_access(self):
portal_user = mail_new_test_user(self.env, login="portal-user", groups="base.group_portal")
Store().add(portal_user.partner_id.with_user(self.user_employee_c2))