From b58fb77f3ac87f4c0bae399dd97e2969caf5c6a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Sainl=C3=A9ger?= Date: Thu, 25 Jun 2026 15:39:30 +0200 Subject: [PATCH] [ADD] helpdesk_user_default_ticket_team: add test coverage Add a ``TransactionCase`` test suite covering the module behaviour: - ``_define_user_id`` decision rules (no team, no current user, user not in team, user in team, team without leader). - ``create`` auto-assignment (with/without partner, with/without default team, explicit team not overridden, partner without linked user, batch ``vals_list`` creation). - ``_compute_user_id`` recomputation on team change. - Full portal creation flow (team + project + user) and presence of the ``default_helpdesk_ticket_team_id`` field on ``res.users``. --- .../tests/__init__.py | 1 + .../tests/test_helpdesk_ticket.py | 399 ++++++++++++++++++ 2 files changed, 400 insertions(+) create mode 100644 helpdesk_user_default_ticket_team/tests/__init__.py create mode 100644 helpdesk_user_default_ticket_team/tests/test_helpdesk_ticket.py diff --git a/helpdesk_user_default_ticket_team/tests/__init__.py b/helpdesk_user_default_ticket_team/tests/__init__.py new file mode 100644 index 0000000..5b42001 --- /dev/null +++ b/helpdesk_user_default_ticket_team/tests/__init__.py @@ -0,0 +1 @@ +from . import test_helpdesk_ticket diff --git a/helpdesk_user_default_ticket_team/tests/test_helpdesk_ticket.py b/helpdesk_user_default_ticket_team/tests/test_helpdesk_ticket.py new file mode 100644 index 0000000..ae44d12 --- /dev/null +++ b/helpdesk_user_default_ticket_team/tests/test_helpdesk_ticket.py @@ -0,0 +1,399 @@ +# Copyright 2025 Stéphan Sainléger (Elabore) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + + +class TestHelpdeskUserDefaultTicketTeam(TransactionCase): + """Tests for helpdesk_user_default_ticket_team module.""" + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + + # ----------------------------------------------------------------- + # Create users + # ----------------------------------------------------------------- + cls.team_leader = cls.env["res.users"].create( + { + "name": "Team Leader", + "login": "team_leader", + "email": "leader@test.com", + } + ) + cls.team_member = cls.env["res.users"].create( + { + "name": "Team Member", + "login": "team_member", + "email": "member@test.com", + } + ) + cls.portal_user = cls.env["res.users"].create( + { + "name": "Portal User", + "login": "portal_user", + "email": "portal@test.com", + } + ) + cls.user_no_team = cls.env["res.users"].create( + { + "name": "No Team User", + "login": "no_team_user", + "email": "noteam@test.com", + } + ) + + # ----------------------------------------------------------------- + # Create a project (needed by helpdesk_mgmt_project) + # ----------------------------------------------------------------- + cls.project = cls.env["project.project"].create( + {"name": "Test Project"} + ) + + # ----------------------------------------------------------------- + # Create helpdesk teams + # ----------------------------------------------------------------- + cls.team_with_leader = cls.env["helpdesk.ticket.team"].create( + { + "name": "Team With Leader", + "user_id": cls.team_leader.id, + "user_ids": [ + (6, 0, [cls.team_leader.id, cls.team_member.id]) + ], + } + ) + cls.team_no_leader = cls.env["helpdesk.ticket.team"].create( + { + "name": "Team No Leader", + "user_ids": [(6, 0, [cls.team_member.id])], + } + ) + cls.team_with_project = cls.env["helpdesk.ticket.team"].create( + { + "name": "Team With Project", + "user_id": cls.team_leader.id, + "user_ids": [(6, 0, [cls.team_leader.id])], + "default_project_id": cls.project.id, + } + ) + cls.empty_team = cls.env["helpdesk.ticket.team"].create( + {"name": "Empty Team"} + ) + + # ----------------------------------------------------------------- + # Assign default teams to users + # ----------------------------------------------------------------- + cls.portal_user.write( + {"default_helpdesk_ticket_team_id": cls.team_with_leader.id} + ) + + # ----------------------------------------------------------------- + # Create a partner linked to the portal user + # ----------------------------------------------------------------- + cls.portal_partner = cls.env["res.partner"].create( + { + "name": "Portal Partner", + "email": "portal@test.com", + } + ) + cls.portal_user.write({"partner_id": cls.portal_partner.id}) + + # Partner for user without default team + cls.no_team_partner = cls.env["res.partner"].create( + { + "name": "No Team Partner", + "email": "noteam@test.com", + } + ) + cls.user_no_team.write({"partner_id": cls.no_team_partner.id}) + + # Partner without any linked user + cls.orphan_partner = cls.env["res.partner"].create( + {"name": "Orphan Partner", "email": "orphan@test.com"} + ) + + # Convenience models + cls.HelpdeskTicket = cls.env["helpdesk.ticket"] + cls.HelpdeskTeam = cls.env["helpdesk.ticket.team"] + + # ----------------------------------------------------------------- + # _define_user_id tests + # ----------------------------------------------------------------- + + def test_define_user_id_no_team(self): + """Without a team, _define_user_id returns the current user_id unchanged.""" + ticket = self.HelpdeskTicket.create( + {"name": "No team ticket", "description": "test"} + ) + result = ticket._define_user_id(team_id=None, ticket_user_id=self.team_member) + self.assertEqual(result, self.team_member) + + def test_define_user_id_no_ticket_user(self): + """With a team but no current user, returns the team leader.""" + ticket = self.HelpdeskTicket.create( + {"name": "Test ticket", "description": "test"} + ) + result = ticket._define_user_id( + team_id=self.team_with_leader, ticket_user_id=None + ) + self.assertEqual(result, self.team_leader) + + def test_define_user_id_user_not_in_team(self): + """When the current user is not in the team, returns the team leader.""" + ticket = self.HelpdeskTicket.create( + {"name": "Test ticket", "description": "test"} + ) + # team_with_leader has team_leader and team_member; user_no_team is not in it + result = ticket._define_user_id( + team_id=self.team_with_leader, ticket_user_id=self.user_no_team + ) + self.assertEqual(result, self.team_leader) + + def test_define_user_id_user_in_team(self): + """When the current user is a team member, they are kept unchanged.""" + ticket = self.HelpdeskTicket.create( + {"name": "Test ticket", "description": "test"} + ) + result = ticket._define_user_id( + team_id=self.team_with_leader, ticket_user_id=self.team_member + ) + self.assertEqual(result, self.team_member) + + def test_define_user_id_team_no_leader(self): + """When the team has no leader, the current user_id is returned unchanged.""" + ticket = self.HelpdeskTicket.create( + {"name": "Test ticket", "description": "test"} + ) + # team_no_leader has no user_id (team leader) + result = ticket._define_user_id( + team_id=self.team_no_leader, ticket_user_id=self.team_member + ) + self.assertEqual(result, self.team_member) + + # ----------------------------------------------------------------- + # create() auto-assignment tests + # ----------------------------------------------------------------- + + def test_create_with_partner_default_team(self): + """Creating a ticket with a partner whose user has a default team + automatically sets the team_id.""" + ticket = self.HelpdeskTicket.create( + { + "name": "Auto team ticket", + "description": "test", + "partner_id": self.portal_partner.id, + } + ) + self.assertEqual( + ticket.team_id, + self.team_with_leader, + "Team should be auto-assigned from the portal user's default team", + ) + + def test_create_with_partner_default_team_and_project(self): + """When the default team has a default_project_id, the ticket gets it.""" + # Give portal_user a default team that has a project + self.portal_user.write( + {"default_helpdesk_ticket_team_id": self.team_with_project.id} + ) + ticket = self.HelpdeskTicket.create( + { + "name": "Auto team+project ticket", + "description": "test", + "partner_id": self.portal_partner.id, + } + ) + self.assertEqual(ticket.team_id, self.team_with_project) + self.assertEqual( + ticket.project_id, + self.project, + "Project should be auto-assigned from the team's default project", + ) + # Reset portal_user default team for other tests + self.portal_user.write( + {"default_helpdesk_ticket_team_id": self.team_with_leader.id} + ) + + def test_create_with_partner_no_default_team(self): + """Creating a ticket with a partner whose user has no default team + does not set a team.""" + ticket = self.HelpdeskTicket.create( + { + "name": "No default team ticket", + "description": "test", + "partner_id": self.no_team_partner.id, + } + ) + self.assertFalse( + ticket.team_id, + "Team should not be set if the user has no default team", + ) + + def test_create_with_explicit_team(self): + """When a team_id is explicitly provided, it is not overridden.""" + ticket = self.HelpdeskTicket.create( + { + "name": "Explicit team ticket", + "description": "test", + "partner_id": self.portal_partner.id, + "team_id": self.team_no_leader.id, + } + ) + self.assertEqual( + ticket.team_id, + self.team_no_leader, + "Explicitly provided team should not be overridden", + ) + + def test_create_without_partner(self): + """Creating a ticket without a partner does not trigger auto-assignment.""" + ticket = self.HelpdeskTicket.create( + {"name": "No partner ticket", "description": "test"} + ) + self.assertFalse( + ticket.team_id, + "Team should not be auto-assigned when there is no partner", + ) + + def test_create_partner_without_user(self): + """Creating a ticket with a partner that has no linked user + does not crash and does not set a team.""" + ticket = self.HelpdeskTicket.create( + { + "name": "Orphan partner ticket", + "description": "test", + "partner_id": self.orphan_partner.id, + } + ) + self.assertFalse( + ticket.team_id, + "Team should not be set when partner has no linked user", + ) + + def test_create_multi_vals_list(self): + """create() with a vals_list processes each ticket independently.""" + tickets = self.HelpdeskTicket.create( + [ + { + "name": "Batch ticket 1", + "description": "test", + "partner_id": self.portal_partner.id, + }, + { + "name": "Batch ticket 2", + "description": "test", + "partner_id": self.no_team_partner.id, + }, + { + "name": "Batch ticket 3", + "description": "test", + }, + ] + ) + self.assertEqual(len(tickets), 3) + # First ticket: portal user with default team + self.assertEqual( + tickets[0].team_id, + self.team_with_leader, + "First batch ticket should get the default team", + ) + # Second ticket: user without default team + self.assertFalse( + tickets[1].team_id, + "Second batch ticket should have no team", + ) + # Third ticket: no partner at all + self.assertFalse( + tickets[2].team_id, + "Third batch ticket should have no team", + ) + + # ----------------------------------------------------------------- + # _compute_user_id tests (depends on team_id) + # ----------------------------------------------------------------- + + def test_compute_user_id_team_change_replaces(self): + """When team_id changes to a team where the current user is not a member, + user_id is replaced by the new team's leader.""" + ticket = self.HelpdeskTicket.create( + { + "name": "Team change ticket", + "description": "test", + "user_id": self.user_no_team.id, + } + ) + # user_no_team is not in team_with_leader members + ticket.team_id = self.team_with_leader + ticket._compute_user_id() + self.assertEqual( + ticket.user_id, + self.team_leader, + "User should be replaced by the new team's leader", + ) + + def test_compute_user_id_team_change_kept(self): + """When team_id changes to a team where the current user is a member, + user_id is kept unchanged.""" + ticket = self.HelpdeskTicket.create( + { + "name": "Team kept ticket", + "description": "test", + "user_id": self.team_member.id, + } + ) + # team_member is in team_with_leader members + ticket.team_id = self.team_with_leader + ticket._compute_user_id() + self.assertEqual( + ticket.user_id, + self.team_member, + "User should stay unchanged when they belong to the new team", + ) + + # ----------------------------------------------------------------- + # Integration test + # ----------------------------------------------------------------- + + def test_full_creation_flow(self): + """Full flow: portal user creates a ticket → default team + project + user + are all set correctly.""" + self.portal_user.write( + {"default_helpdesk_ticket_team_id": self.team_with_project.id} + ) + ticket = self.HelpdeskTicket.create( + { + "name": "Full flow ticket", + "description": "test", + "partner_id": self.portal_partner.id, + } + ) + # Team auto-assigned from portal user's default + self.assertEqual(ticket.team_id, self.team_with_project) + # Project auto-assigned from team's default project + self.assertEqual(ticket.project_id, self.project) + # User auto-assigned to team leader (since no user was provided) + self.assertEqual(ticket.user_id, self.team_leader) + # Reset + self.portal_user.write( + {"default_helpdesk_ticket_team_id": self.team_with_leader.id} + ) + + # ----------------------------------------------------------------- + # res.users field test + # ----------------------------------------------------------------- + + def test_user_default_team_field(self): + """The default_helpdesk_ticket_team_id field exists on res.users.""" + self.assertIn( + "default_helpdesk_ticket_team_id", + self.env["res.users"]._fields, + "Field default_helpdesk_ticket_team_id must exist on res.users", + ) + self.assertEqual( + self.portal_user.default_helpdesk_ticket_team_id, + self.team_with_leader, + ) + self.assertFalse( + self.user_no_team.default_helpdesk_ticket_team_id, + )