From 13cf3f81522f3d518056d17ae1dafd23955c695e Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 18 Jul 2025 17:32:01 +0930 Subject: [PATCH] refactor(core): Update Test Suite for TicketCommentBase model ref: #871 #865 --- app/core/models/ticket_comment_base.py | 81 ++++++++---- .../test_ticket_comment_viewset.py | 27 ---- ...st_functional_ticket_comment_base_model.py | 3 +- .../unit/ticket_comment_base/conftest.py | 3 - ...est_unit_ticket_comment_base_api_fields.py | 12 +- .../test_unit_ticket_comment_base_model.py | 125 +++++++++++++++--- .../test_unit_ticket_comment_base_viewset.py | 3 + app/tests/fixtures/model_ticketbase.py | 5 +- 8 files changed, 181 insertions(+), 78 deletions(-) diff --git a/app/core/models/ticket_comment_base.py b/app/core/models/ticket_comment_base.py index 34b56d74..04d73798 100644 --- a/app/core/models/ticket_comment_base.py +++ b/app/core/models/ticket_comment_base.py @@ -1,6 +1,7 @@ import datetime from django.apps import apps +from django.conf import settings from django.db import models from rest_framework.reverse import reverse @@ -9,7 +10,6 @@ from access.fields import AutoCreatedField, AutoLastModifiedField from access.models.entity import Entity from core import exceptions as centurion_exception -from core.lib.feature_not_used import FeatureNotUsed from core.lib.slash_commands import SlashCommands from core.models.centurion import CenturionModel from core.models.ticket_base import TicketBase @@ -29,8 +29,12 @@ class TicketCommentBase( model_notes = None + model_tag = None + save_model_history: bool = False + url_model_name = 'ticket_comment_base' + class Meta: @@ -257,7 +261,8 @@ class TicketCommentBase( if self.is_closed and self.date_closed is None: - self.date_closed = datetime.datetime.now(tz=datetime.timezone.utc).replace(microsecond=0).isoformat() + self.date_closed = datetime.datetime.now(tz=datetime.timezone.utc).replace( + microsecond=0).isoformat() if self.comment_type != self._meta.sub_model_type: @@ -280,7 +285,7 @@ class TicketCommentBase( self.organization = self.ticket.organization - return super().clean_fields(exclude) + super().clean_fields(exclude = exclude) @@ -343,40 +348,62 @@ class TicketCommentBase( - def get_url( self, request = None ) -> str: + def get_url( + self, relative: bool = False, api_version: int = 2, many = False, request: any = None + ) -> str: - kwargs = self.get_url_kwargs() + namespace = f'v{api_version}' + + if self.get_app_namespace(): + namespace = namespace + ':' + self.get_app_namespace() + + + url_basename = f'{namespace}:_api_{self._meta.model_name}' + + if self.url_model_name: + + url_basename = f'{namespace}:_api_{self.url_model_name}' + + if self._is_submodel: + + url_basename += '_sub' if self.parent: - url_name = '_api_ticket_comment_base_sub_thread' + url_basename += '_thread' + + + if many: + + url_basename += '-list' else: - url_name = '_api_ticket_comment_base_sub' + url_basename += '-detail' - if request: + url = reverse( viewname = url_basename, kwargs = self.get_url_kwargs( many = many ) ) - return reverse('v2:' + url_name + '-detail', request=request, kwargs = kwargs ) + if not relative: + + url = settings.SITE_URL + url - return reverse('v2:' + url_name + '-detail', kwargs = kwargs ) + return url - def get_url_kwargs(self) -> dict: + def get_url_kwargs(self, many = False) -> dict: + kwargs = {} - kwargs = { - 'ticket_comment_model': self.comment_type, + if self._is_submodel: + kwargs = { + 'ticket_comment_model': self._meta.sub_model_type + } + + kwargs.update({ 'ticket_id': self.ticket.id, - } - - if self.pk: - - kwargs.update({ - 'pk': self.id - }) + }) if self.parent: @@ -385,13 +412,16 @@ class TicketCommentBase( }) + if not many: + + kwargs.update({ + 'pk': self.id + }) + + return kwargs - def get_url_kwargs_notes(self): - - return FeatureNotUsed - @property def parent_object(self): @@ -420,7 +450,8 @@ class TicketCommentBase( or self.comment_type == self.CommentType.SOLUTION ): - super().save(force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields) + super().save(force_insert=force_insert, force_update=force_update, + using=using, update_fields=update_fields) # clear ticket comment cache if hasattr(self.ticket, '_ticket_comments'): diff --git a/app/core/tests/functional/ticket_comment/test_ticket_comment_viewset.py b/app/core/tests/functional/ticket_comment/test_ticket_comment_viewset.py index 999adf7b..d7cb46cd 100644 --- a/app/core/tests/functional/ticket_comment/test_ticket_comment_viewset.py +++ b/app/core/tests/functional/ticket_comment/test_ticket_comment_viewset.py @@ -233,33 +233,6 @@ class ViewSetBase: ) -class TicketCommentPermissionsAPI( - ViewSetBase, - APIPermissions, - TestCase -): - def test_returned_results_only_user_orgs(self): - """Test not required - - this test is not required as a ticket comment obtains it's - organization from the ticket. - """ - - pass - - - def test_returned_data_from_user_and_global_organizations_only(self): - """Check items returned - - This test case is a over-ride of a test case with the same name. - This model is not a tenancy model making this test not-applicable. - - Items returned from the query Must be from the users organization and - global ONLY! - """ - pass - - class TicketCommentMetadata( ViewSetBase, diff --git a/app/core/tests/functional/ticket_comment_base/test_functional_ticket_comment_base_model.py b/app/core/tests/functional/ticket_comment_base/test_functional_ticket_comment_base_model.py index 57d41726..1ef68747 100644 --- a/app/core/tests/functional/ticket_comment_base/test_functional_ticket_comment_base_model.py +++ b/app/core/tests/functional/ticket_comment_base/test_functional_ticket_comment_base_model.py @@ -1,10 +1,10 @@ import pytest -from core.models.ticket.ticket import Ticket from core.tests.functional.slash_commands.test_slash_command_related import SlashCommandsTicketCommentInheritedTestCases +@pytest.mark.model_ticketcommentbase class TicketCommentBaseModelTestCases( SlashCommandsTicketCommentInheritedTestCases ): @@ -82,6 +82,7 @@ class TicketCommentBaseModelInheritedTestCases( +@pytest.mark.module_core class TicketCommentBaseModelPyTest( TicketCommentBaseModelTestCases ): diff --git a/app/core/tests/unit/ticket_comment_base/conftest.py b/app/core/tests/unit/ticket_comment_base/conftest.py index c422769c..a40d1b41 100644 --- a/app/core/tests/unit/ticket_comment_base/conftest.py +++ b/app/core/tests/unit/ticket_comment_base/conftest.py @@ -18,6 +18,3 @@ def model_kwargs(request, kwargs_ticketcommentbase): request.cls.kwargs_create_item = kwargs_ticketcommentbase.copy() yield kwargs_ticketcommentbase.copy() - - if hasattr(request.cls, 'kwargs_create_item'): - del request.cls.kwargs_create_item diff --git a/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_api_fields.py b/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_api_fields.py index e1794b85..a0ca3613 100644 --- a/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_api_fields.py +++ b/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_api_fields.py @@ -23,6 +23,7 @@ User = django.contrib.auth.get_user_model() +@pytest.mark.model_ticketcommentbase class TicketCommentBaseAPITestCases( APIFieldsInheritedCases, ): @@ -107,9 +108,15 @@ class TicketCommentBaseAPITestCases( with django_db_blocker.unblock(): - template_comment.delete() + try: + template_comment.delete() + except: + pass - category.delete() + try: + category.delete() + except: + pass del request.cls.comment_user @@ -370,6 +377,7 @@ class TicketCommentBaseAPIInheritedCases( +@pytest.mark.module_core class TicketCommentBaseAPIPyTest( TicketCommentBaseAPITestCases, ): diff --git a/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_model.py b/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_model.py index d3a1a438..fc2330cf 100644 --- a/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_model.py +++ b/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_model.py @@ -1,4 +1,4 @@ - +import datetime import pytest from django.db import models @@ -29,14 +29,17 @@ class TicketCommentBaseModelTestCases( '_notes_enabled': { 'value': False }, + '_is_submodel': { + 'value': False + }, 'model_tag': { - 'type': None, + 'type': type(None), 'value': None }, - # 'url_model_name': { - # 'type': str, - # 'value': 'ticket' - # }, + 'url_model_name': { + 'type': str, + 'value': 'ticket_comment_base' + }, } @@ -159,6 +162,45 @@ class TicketCommentBaseModelTestCases( } + @pytest.fixture + def ticket(self, request, django_db_blocker, model_ticketbase, kwargs_ticketbase): + + random_str = str(datetime.datetime.now(tz=datetime.timezone.utc)) + random_str = str(random_str).replace( + ' ', '').replace(':', '').replace('+', '').replace('.', '') + + with django_db_blocker.unblock(): + + kwargs = kwargs_ticketbase.copy() + + del kwargs['external_system'] + del kwargs['external_ref'] + + kwargs['title'] = 'fn_ticket_' + str(random_str) + + ticket = model_ticketbase.objects.create( + **kwargs, + ) + + yield ticket + + + with django_db_blocker.unblock(): + + for comment in ticket.ticketcommentbase_set.all(): + + comment.delete() + + ticket.delete() + + + def test_method_value_not_default___str__(self, model, model_instance ): + pytest.xfail( reason = 'model does not require this function' ) + + + def test_model_tag_defined(self, model): + pytest.xfail( reason = 'model does not require this function' ) + def test_class_inherits_TicketCommentBase(self, model): """ Class inheritence @@ -341,7 +383,32 @@ class TicketCommentBaseModelTestCases( model_instance.ticket.id) + '/' + self.sub_model_type + '/' + str( model_instance.id) - assert model_instance.get_url() == '/api/v2' + expected_value + assert model_instance.get_url(relative = True) == '/api/v2' + expected_value + + + + + def test_method_get_url_kwargs(self, mocker, model_instance, settings): + """Test Class Method + + Ensure method `get_url_kwargs` returns the correct value. + """ + + + url = model_instance.get_url_kwargs() + + kwargs = { + 'ticket_id': model_instance.ticket.id, + 'pk': model_instance.id, + } + + if model_instance._is_submodel: + kwargs.update({ + 'ticket_comment_model': model_instance._meta.sub_model_type + }) + + assert model_instance.get_url_kwargs() == kwargs + def test_function_parent_object(self, model_instance): @@ -373,7 +440,7 @@ class TicketCommentBaseModelTestCases( - def test_function_called_clean_ticketcommentbase(self, model, mocker, model_instance): + def test_function_called_clean_ticketcommentbase(self, model, mocker, ticket): """Function Check Ensure function `TicketCommentBase.clean` is called @@ -383,10 +450,10 @@ class TicketCommentBaseModelTestCases( valid_data = self.kwargs_create_item.copy() - valid_data['ticket'] = model_instance + valid_data['ticket'] = ticket - del valid_data['external_system'] - del valid_data['external_ref'] + # del valid_data['external_system'] + # del valid_data['external_ref'] comment = model.objects.create( **valid_data @@ -397,7 +464,7 @@ class TicketCommentBaseModelTestCases( assert spy.assert_called_once - def test_function_save_called_slash_command(self, model, mocker, model_instance): + def test_function_save_called_slash_command(self, model, mocker, ticket): """Function Check Ensure function `TicketCommentBase.clean` is called @@ -407,10 +474,10 @@ class TicketCommentBaseModelTestCases( valid_data = self.kwargs_create_item.copy() - valid_data['ticket'] = model_instance + valid_data['ticket'] = ticket - del valid_data['external_system'] - del valid_data['external_ref'] + # del valid_data['external_system'] + # del valid_data['external_ref'] item = model.objects.create( **valid_data @@ -460,7 +527,7 @@ class TicketCommentBaseModelPyTest( # assert err.value.get_codes()['date_closed'] == 'ticket_closed_no_date' - def test_function_save_called_slash_command(self, model, mocker, model_instance): + def test_function_save_called_slash_command(self, model, mocker, ticket): """Function Check This test case is a duplicate of a test with the same name. This @@ -473,13 +540,33 @@ class TicketCommentBaseModelPyTest( valid_data = self.kwargs_create_item.copy() - valid_data['ticket'] = model_instance + valid_data['ticket'] = ticket - del valid_data['external_system'] - del valid_data['external_ref'] + # del valid_data['external_system'] + # del valid_data['external_ref'] item = model.objects.create( **valid_data ) spy.assert_called_with(item, valid_data['body']) + + def test_function_get_url(self, model_instance): + """Function Check + + Confirm function `get_url` returns the correct url + """ + + if model_instance.parent: + + expected_value = '/core/ticket/' + str( + model_instance.ticket.id) + '/comment/' + str( + model_instance.parent.id) + '/threads/' + str(model_instance.id) + + else: + + expected_value = '/core/ticket/' + str( + model_instance.ticket.id) + '/comment/' + str( + model_instance.id) + + assert model_instance.get_url(relative = True) == '/api/v2' + expected_value diff --git a/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_viewset.py b/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_viewset.py index 98836474..4c13dc2a 100644 --- a/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_viewset.py +++ b/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_viewset.py @@ -1,4 +1,5 @@ import django +import pytest from django.test import Client, TestCase @@ -17,6 +18,7 @@ User = django.contrib.auth.get_user_model() +@pytest.mark.model_ticketcommentbase class TicketCommentBaseViewsetTestCases( SubModelViewSetInheritedCases, ): @@ -113,6 +115,7 @@ class TicketCommentBaseViewsetInheritedCases( +@pytest.mark.module_core class TicketCommentBaseViewsetTest( TicketCommentBaseViewsetTestCases, TestCase, diff --git a/app/tests/fixtures/model_ticketbase.py b/app/tests/fixtures/model_ticketbase.py index d447d97b..6713d445 100644 --- a/app/tests/fixtures/model_ticketbase.py +++ b/app/tests/fixtures/model_ticketbase.py @@ -40,4 +40,7 @@ def kwargs_ticketbase(django_db_blocker, kwargs_centurionmodel, with django_db_blocker.unblock(): - user.delete() \ No newline at end of file + try: + user.delete() + except: + pass \ No newline at end of file