refactor(core): Initial Update Test Suite for TicketCommentBase model

ref: #871 #865
This commit is contained in:
2025-07-17 00:12:13 +09:30
parent 27e842a57f
commit 9d78d112ec
5 changed files with 220 additions and 304 deletions

View File

@ -140,7 +140,7 @@ class TicketCommentBase(
field_validation_not_empty field_validation_not_empty
], ],
verbose_name = 'Type', verbose_name = 'Type',
) )
category = models.ForeignKey( category = models.ForeignKey(
TicketCommentCategory, TicketCommentCategory,
@ -208,7 +208,7 @@ class TicketCommentBase(
help_text = 'Origin type for this comment', help_text = 'Origin type for this comment',
null = False, null = False,
verbose_name = 'Source', verbose_name = 'Source',
) )
user = models.ForeignKey( user = models.ForeignKey(
Entity, Entity,
@ -331,7 +331,7 @@ class TicketCommentBase(
if getattr(self, related_object.name, None): if getattr(self, related_object.name, None):
if( if(
not str(related_object.name).endswith('history') not str(related_object.name).endswith('history')
and not str(related_object.name).endswith('notes') and not str(related_object.name).endswith('notes')
): ):
@ -396,7 +396,7 @@ class TicketCommentBase(
@property @property
def parent_object(self): def parent_object(self):
""" Fetch the parent object """ """ Fetch the parent object """
return self.ticket return self.ticket

View File

@ -1,14 +1,23 @@
import pytest import pytest
from core.models.ticket_comment_base import TicketCommentBase
@pytest.fixture( scope = 'class') @pytest.fixture( scope = 'class')
def model(request): def model(request, model_ticketcommentbase):
request.cls.model = TicketCommentBase request.cls.model = model_ticketcommentbase
yield request.cls.model yield request.cls.model
del request.cls.model del request.cls.model
@pytest.fixture( scope = 'class', autouse = True)
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

View File

@ -1,264 +1,172 @@
import datetime
import django
import pytest import pytest
from django.db import models from django.db import models
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from access.models.person import Person
from centurion.tests.unit.test_unit_models import ( from core.models.ticket_comment_base import TicketCommentBase, TicketBase
PyTestTenancyObjectInheritedCases, from core.tests.unit.centurion_abstract.test_unit_centurion_abstract_model import (
CenturionAbstractModelInheritedCases
) )
from core.models.ticket_comment_base import TicketBase, TicketCommentBase, TicketCommentCategory
User = django.contrib.auth.get_user_model()
@pytest.mark.model_ticketcommentbase
class TicketCommentBaseModelTestCases( class TicketCommentBaseModelTestCases(
PyTestTenancyObjectInheritedCases, CenturionAbstractModelInheritedCases
): ):
base_model = TicketCommentBase
sub_model_type = 'comment' @property
"""Sub Model Type def parameterized_class_attributes(self):
sub-models must have this attribute defined in `ModelName.Meta.sub_model_type`
"""
kwargs_create_item: dict = { return {
'parent': None, '_audit_enabled': {
'ticket': '', 'value': False
'external_ref': 0, },
'external_system': TicketBase.Ticket_ExternalSystem.CUSTOM_1, '_notes_enabled': {
'comment_type': sub_model_type, 'value': False
'category': '', },
'body': 'asdasdas', 'model_tag': {
'private': False, 'type': None,
'template': None, 'value': None
'source': TicketBase.TicketSource.HELPDESK, },
'user': '', # 'url_model_name': {
'is_closed': True, # 'type': str,
'date_closed': '2025-05-08T17:10Z', # 'value': 'ticket'
} # },
}
parameterized_fields: dict = { @property
"model_notes": { def parameterized_model_fields(self):
'field_type': None,
'field_parameter_default_exists': None,
'field_parameter_default_value': None,
'field_parameter_verbose_name_type': None
},
"parent": {
'field_type': models.ForeignKey,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
"ticket": {
'field_type': models.ForeignKey,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
"external_ref": {
'field_type': models.fields.IntegerField,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
"external_system": {
'field_type': models.fields.IntegerField,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
"comment_type": {
'field_type': models.fields.CharField,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
"category": {
'field_type': models.ForeignKey,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
"body": {
'field_type': models.fields.TextField,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
"private": {
'field_type': models.fields.BooleanField,
'field_parameter_default_exists': True,
'field_parameter_default_value': False,
'field_parameter_verbose_name_type': str,
},
"duration": {
'field_type': models.fields.IntegerField,
'field_parameter_default_exists': True,
'field_parameter_default_value': 0,
'field_parameter_verbose_name_type': str,
},
"estimation": {
'field_type': models.fields.IntegerField,
'field_parameter_default_exists': True,
'field_parameter_default_value': 0,
'field_parameter_verbose_name_type': str,
},
"template": {
'field_type': models.ForeignKey,
'field_parameter_default_exists': True,
'field_parameter_verbose_name_type': str,
},
"source": {
'field_type': models.fields.IntegerField,
'field_parameter_default_exists': True,
'field_parameter_default_value': TicketBase.TicketSource.HELPDESK,
'field_parameter_verbose_name_type': str,
},
"user": {
'field_type': models.ForeignKey,
'field_parameter_default_exists': False,
'field_parameter_default_value': None,
'field_parameter_verbose_name_type': str,
},
"is_closed": {
'field_type': models.fields.BooleanField,
'field_parameter_default_exists': True,
'field_parameter_default_value': False,
'field_parameter_verbose_name_type': str,
},
"date_closed": {
'field_type': models.fields.DateTimeField,
'field_parameter_default_exists': False,
'field_parameter_verbose_name_type': str,
},
}
return {
@pytest.fixture( scope = 'class') "model_notes": {
def setup_model(self, 'blank': models.fields.NOT_PROVIDED,
request, 'default': models.fields.NOT_PROVIDED,
model, 'field_type': models.fields.NOT_PROVIDED,
django_db_blocker, 'null': models.fields.NOT_PROVIDED,
organization_one, 'unique': models.fields.NOT_PROVIDED,
organization_two },
): "parent": {
'blank': True,
request.cls.model = model 'default': models.fields.NOT_PROVIDED,
'field_type': models.ForeignKey,
with django_db_blocker.unblock(): 'null': True,
'unique': False,
random_str = datetime.datetime.now(tz=datetime.timezone.utc) },
"ticket": {
request.cls.organization = organization_one 'blank': False,
'default': models.fields.NOT_PROVIDED,
request.cls.different_organization = organization_two 'field_type': models.ForeignKey,
'null': False,
kwargs_create_item = {} 'unique': False,
},
for base in reversed(request.cls.__mro__): "external_ref": {
'blank': True,
if hasattr(base, 'kwargs_create_item'): 'default': models.fields.NOT_PROVIDED,
'field_type': models.fields.IntegerField,
if base.kwargs_create_item is None: 'null': True,
'unique': False,
continue },
"external_system": {
kwargs_create_item.update(**base.kwargs_create_item) 'blank': True,
'default': models.fields.NOT_PROVIDED,
'field_type': models.fields.IntegerField,
if len(kwargs_create_item) > 0: 'null': True,
'unique': False,
request.cls.kwargs_create_item = kwargs_create_item },
"comment_type": {
'blank': False,
request.cls.view_user = User.objects.create_user(username="ticket_comment_user_"+ str(random_str), password="password") 'default': models.fields.NOT_PROVIDED,
'field_type': models.fields.CharField,
comment_category = TicketCommentCategory.objects.create( 'null': False,
organization = request.cls.organization, 'unique': False,
name = 'test cat comment'+ str(random_str) },
) "category": {
'blank': True,
ticket = TicketBase.objects.create( 'default': models.fields.NOT_PROVIDED,
organization = request.cls.organization, 'field_type': models.ForeignKey,
title = 'tester comment ticket'+ str(random_str), 'null': True,
description = 'aa', 'unique': False,
opened_by = request.cls.view_user, },
) "body": {
'blank': True,
user = Person.objects.create( 'default': models.fields.NOT_PROVIDED,
organization = request.cls.organization, 'field_type': models.fields.TextField,
f_name = 'ip'+ str(random_str), 'null': True,
l_name = 'funny' 'unique': False,
) },
"private": {
request.cls.kwargs_create_item.update({ 'blank': False,
'category': comment_category, 'default': False,
'ticket': ticket, 'field_type': models.fields.BooleanField,
'user': user, 'null': False,
}) 'unique': False,
},
"duration": {
if 'organization' not in request.cls.kwargs_create_item: 'blank': False,
'default': 0,
request.cls.kwargs_create_item.update({ 'field_type': models.fields.IntegerField,
'organization': request.cls.organization 'null': False,
}) 'unique': False,
},
yield "estimation": {
'blank': False,
with django_db_blocker.unblock(): 'default': 0,
'field_type': models.fields.IntegerField,
del request.cls.kwargs_create_item 'null': False,
'unique': False,
comment_category.delete() },
"template": {
for comment in ticket.ticketcommentbase_set.all(): 'blank': True,
'default': models.fields.NOT_PROVIDED,
comment.delete() 'field_type': models.ForeignKey,
'null': True,
ticket.delete() 'unique': False,
},
user.delete() "source": {
'blank': False,
request.cls.view_user.delete() 'default': TicketBase.TicketSource.HELPDESK,
'field_type': models.fields.IntegerField,
'null': False,
'unique': False,
},
"user": {
'blank': False,
'default': models.fields.NOT_PROVIDED,
'field_type': models.ForeignKey,
'null': True,
'unique': False,
},
"is_closed": {
'blank': False,
'default': False,
'field_type': models.fields.IntegerField,
'null': False,
'unique': False,
},
"date_closed": {
'blank': True,
'default': models.fields.NOT_PROVIDED,
'field_type': models.fields.DateTimeField,
'null': True,
'unique': False,
}
}
@pytest.fixture( scope = 'class', autouse = True) def test_class_inherits_TicketCommentBase(self, model):
def class_setup(self, """ Class inheritence
setup_model,
create_model,
):
pass TenancyObject must inherit SaveHistory
"""
assert issubclass(model, TicketCommentBase)
@pytest.fixture
def ticket(self, request, django_db_blocker):
with django_db_blocker.unblock():
ticket = TicketBase.objects.create(
organization = request.cls.organization,
title = 'per function_ticket',
opened_by = request.cls.view_user,
)
yield ticket
with django_db_blocker.unblock():
for comment in ticket.ticketcommentbase_set.all():
comment.delete()
ticket.delete()
def test_create_validation_exception_no_organization(self): def test_create_validation_exception_no_organization(self):
@ -273,43 +181,43 @@ class TicketCommentBaseModelTestCases(
pass pass
def test_class_inherits_ticketcommentbase(self): def test_class_inherits_ticketcommentbase(self, model):
""" Class inheritence """ Class inheritence
TenancyObject must inherit SaveHistory TenancyObject must inherit SaveHistory
""" """
assert issubclass(self.model, TicketCommentBase) assert issubclass(model, TicketCommentBase)
def test_attribute_meta_exists_permissions(self): def test_attribute_meta_exists_permissions(self, model):
"""Attribute Check """Attribute Check
Ensure attribute `Meta.permissions` exists Ensure attribute `Meta.permissions` exists
""" """
assert hasattr(self.model._meta, 'permissions') assert hasattr(model._meta, 'permissions')
def test_attribute_meta_not_none_permissions(self): def test_attribute_meta_not_none_permissions(self, model):
"""Attribute Check """Attribute Check
Ensure attribute `Meta.permissions` does not have a value of none Ensure attribute `Meta.permissions` does not have a value of none
""" """
assert self.model._meta.permissions is not None assert model._meta.permissions is not None
def test_attribute_meta_type_permissions(self): def test_attribute_meta_type_permissions(self, model):
"""Attribute Check """Attribute Check
Ensure attribute `Meta.permissions` value is of type list Ensure attribute `Meta.permissions` value is of type list
""" """
assert type(self.model._meta.permissions) is list assert type(model._meta.permissions) is list
def test_attribute_value_permissions_has_import(self): def test_attribute_value_permissions_has_import(self, model):
"""Attribute Check """Attribute Check
Ensure attribute `Meta.permissions` value contains permission Ensure attribute `Meta.permissions` value contains permission
@ -318,9 +226,9 @@ class TicketCommentBaseModelTestCases(
permission_found = False permission_found = False
for permission, description in self.model._meta.permissions: for permission, description in model._meta.permissions:
if permission == 'import_' + self.model._meta.model_name: if permission == 'import_' + model._meta.model_name:
permission_found = True permission_found = True
break break
@ -328,7 +236,7 @@ class TicketCommentBaseModelTestCases(
assert permission_found assert permission_found
def test_attribute_value_permissions_has_triage(self): def test_attribute_value_permissions_has_triage(self, model):
"""Attribute Check """Attribute Check
Ensure attribute `Meta.permissions` value contains permission Ensure attribute `Meta.permissions` value contains permission
@ -337,9 +245,9 @@ class TicketCommentBaseModelTestCases(
permission_found = False permission_found = False
for permission, description in self.model._meta.permissions: for permission, description in model._meta.permissions:
if permission == 'triage_' + self.model._meta.model_name: if permission == 'triage_' + model._meta.model_name:
permission_found = True permission_found = True
break break
@ -347,7 +255,7 @@ class TicketCommentBaseModelTestCases(
assert permission_found assert permission_found
def test_attribute_value_permissions_has_purge(self): def test_attribute_value_permissions_has_purge(self, model):
"""Attribute Check """Attribute Check
Ensure attribute `Meta.permissions` value contains permission Ensure attribute `Meta.permissions` value contains permission
@ -356,9 +264,9 @@ class TicketCommentBaseModelTestCases(
permission_found = False permission_found = False
for permission, description in self.model._meta.permissions: for permission, description in model._meta.permissions:
if permission == 'purge_' + self.model._meta.model_name: if permission == 'purge_' + model._meta.model_name:
permission_found = True permission_found = True
break break
@ -366,83 +274,86 @@ class TicketCommentBaseModelTestCases(
assert permission_found assert permission_found
def test_attribute_meta_type_sub_model_type(self): def test_attribute_meta_type_sub_model_type(self, model):
"""Attribute Check """Attribute Check
Ensure attribute `Meta.sub_model_type` value is of type str Ensure attribute `Meta.sub_model_type` value is of type str
""" """
assert type(self.model._meta.sub_model_type) is str assert type(model._meta.sub_model_type) is str
def test_attribute_meta_value_sub_model_type(self): def test_attribute_meta_value_sub_model_type(self, model):
"""Attribute Check """Attribute Check
Ensure attribute `Meta.sub_model_type` value is correct Ensure attribute `Meta.sub_model_type` value is correct
""" """
assert self.model._meta.sub_model_type == self.sub_model_type assert model._meta.sub_model_type == self.sub_model_type
def test_attribute_type_get_comment_type(self): def test_attribute_type_get_comment_type(self, model_instance):
"""Attribute Check """Attribute Check
Ensure attribute `get_comment_type` value is correct Ensure attribute `get_comment_type` value is correct
""" """
assert self.item.get_comment_type == self.item._meta.sub_model_type assert model_instance.get_comment_type == model_instance._meta.sub_model_type
def test_function_get_related_model(self): def test_function_get_related_model(self, model_instance):
"""Function Check """Function Check
Confirm function `get_related_model` returns `None` for self Confirm function `get_related_model` returns `None` for self
""" """
assert self.item.get_related_model() == None assert model_instance.get_related_model() == None
def test_function_get_related_field_name(self): def test_function_get_related_field_name(self, model_instance):
"""Function Check """Function Check
Confirm function `get_related_field_name` returns an empty string Confirm function `get_related_field_name` returns an empty string
for self for self
""" """
assert self.item.get_related_field_name() == '' assert model_instance.get_related_field_name() == ''
def test_function_get_url(self): def test_function_get_url(self, model_instance):
"""Function Check """Function Check
Confirm function `get_url` returns the correct url Confirm function `get_url` returns the correct url
""" """
if self.item.parent: if model_instance.parent:
expected_value = '/core/ticket/' + str(self.item.ticket.id) + '/' + self.sub_model_type + '/' + str( expected_value = '/core/ticket/' + str(
self.item.parent.id) + '/threads/' + str(self.item.id) model_instance.ticket.id) + '/' + self.sub_model_type + '/' + str(
model_instance.parent.id) + '/threads/' + str(model_instance.id)
else: else:
expected_value = '/core/ticket/' + str( self.item.ticket.id) + '/' + self.sub_model_type + '/' + str(self.item.id) expected_value = '/core/ticket/' + str(
model_instance.ticket.id) + '/' + self.sub_model_type + '/' + str(
model_instance.id)
assert self.item.get_url() == '/api/v2' + expected_value assert model_instance.get_url() == '/api/v2' + expected_value
def test_function_parent_object(self): def test_function_parent_object(self, model_instance):
"""Function Check """Function Check
Confirm function `parent_object` returns the ticket Confirm function `parent_object` returns the ticket
""" """
assert self.item.parent_object == self.item.ticket assert model_instance.parent_object == model_instance.ticket
def test_function_clean_validation_mismatch_comment_type_raises_exception(self): def test_function_clean_validation_mismatch_comment_type_raises_exception(self, model):
"""Function Check """Function Check
Ensure function `clean` does validation Ensure function `clean` does validation
@ -454,7 +365,7 @@ class TicketCommentBaseModelTestCases(
with pytest.raises(ValidationError) as err: with pytest.raises(ValidationError) as err:
self.model.objects.create( model.objects.create(
**valid_data **valid_data
) )
@ -462,7 +373,7 @@ class TicketCommentBaseModelTestCases(
def test_function_called_clean_ticketcommentbase(self, model, mocker, ticket): def test_function_called_clean_ticketcommentbase(self, model, mocker, model_instance):
"""Function Check """Function Check
Ensure function `TicketCommentBase.clean` is called Ensure function `TicketCommentBase.clean` is called
@ -472,7 +383,7 @@ class TicketCommentBaseModelTestCases(
valid_data = self.kwargs_create_item.copy() valid_data = self.kwargs_create_item.copy()
valid_data['ticket'] = ticket valid_data['ticket'] = model_instance
del valid_data['external_system'] del valid_data['external_system']
del valid_data['external_ref'] del valid_data['external_ref']
@ -486,17 +397,17 @@ class TicketCommentBaseModelTestCases(
assert spy.assert_called_once assert spy.assert_called_once
def test_function_save_called_slash_command(self, model, mocker, ticket): def test_function_save_called_slash_command(self, model, mocker, model_instance):
"""Function Check """Function Check
Ensure function `TicketCommentBase.clean` is called Ensure function `TicketCommentBase.clean` is called
""" """
spy = mocker.spy(self.model, 'slash_command') spy = mocker.spy(model, 'slash_command')
valid_data = self.kwargs_create_item.copy() valid_data = self.kwargs_create_item.copy()
valid_data['ticket'] = ticket valid_data['ticket'] = model_instance
del valid_data['external_system'] del valid_data['external_system']
del valid_data['external_ref'] del valid_data['external_ref']
@ -512,28 +423,19 @@ class TicketCommentBaseModelTestCases(
class TicketCommentBaseModelInheritedCases( class TicketCommentBaseModelInheritedCases(
TicketCommentBaseModelTestCases, TicketCommentBaseModelTestCases,
): ):
"""Sub-Ticket Test Cases
Test Cases for Ticket models that inherit from model TicketCommentBase
"""
kwargs_create_item: dict = {}
model = None
sub_model_type = None sub_model_type = None
"""Ticket Sub Model Type
Ticket sub-models must have this attribute defined in `ModelNam.Meta.sub_model_type`
"""
@pytest.mark.module_core
class TicketCommentBaseModelPyTest( class TicketCommentBaseModelPyTest(
TicketCommentBaseModelTestCases, TicketCommentBaseModelTestCases,
): ):
sub_model_type = 'comment'
# def test_function_clean_validation_close_raises_exception(self, ticket): # def test_function_clean_validation_close_raises_exception(self, ticket):
# """Function Check # """Function Check
@ -558,7 +460,7 @@ class TicketCommentBaseModelPyTest(
# assert err.value.get_codes()['date_closed'] == 'ticket_closed_no_date' # assert err.value.get_codes()['date_closed'] == 'ticket_closed_no_date'
def test_function_save_called_slash_command(self, model, mocker, ticket): def test_function_save_called_slash_command(self, model, mocker, model_instance):
"""Function Check """Function Check
This test case is a duplicate of a test with the same name. This This test case is a duplicate of a test with the same name. This
@ -567,11 +469,11 @@ class TicketCommentBaseModelPyTest(
Ensure function `TicketCommentBase.clean` is called Ensure function `TicketCommentBase.clean` is called
""" """
spy = mocker.spy(self.model, 'slash_command') spy = mocker.spy(model, 'slash_command')
valid_data = self.kwargs_create_item.copy() valid_data = self.kwargs_create_item.copy()
valid_data['ticket'] = ticket valid_data['ticket'] = model_instance
del valid_data['external_system'] del valid_data['external_system']
del valid_data['external_ref'] del valid_data['external_ref']

View File

@ -13,7 +13,8 @@ def model_ticketcommentbase(request):
@pytest.fixture( scope = 'class') @pytest.fixture( scope = 'class')
def kwargs_ticketcommentbase(django_db_blocker, kwargs_centurionmodel, def kwargs_ticketcommentbase(django_db_blocker, kwargs_centurionmodel,
model_person, kwargs_person, model_ticketcommentbase model_person, kwargs_person, model_ticketcommentbase,
model_ticketbase, kwargs_ticketbase
): ):
random_str = str(datetime.datetime.now(tz=datetime.timezone.utc)) random_str = str(datetime.datetime.now(tz=datetime.timezone.utc))
@ -24,6 +25,8 @@ def kwargs_ticketcommentbase(django_db_blocker, kwargs_centurionmodel,
person = model_person.objects.create( **kwargs_person ) person = model_person.objects.create( **kwargs_person )
ticket = model_ticketbase.objects.create( **kwargs_ticketbase )
kwargs = kwargs_centurionmodel.copy() kwargs = kwargs_centurionmodel.copy()
del kwargs['model_notes'] del kwargs['model_notes']
@ -31,6 +34,7 @@ def kwargs_ticketcommentbase(django_db_blocker, kwargs_centurionmodel,
**kwargs, **kwargs,
'body': 'a comment body', 'body': 'a comment body',
'comment_type': model_ticketcommentbase._meta.sub_model_type, 'comment_type': model_ticketcommentbase._meta.sub_model_type,
'ticket': ticket,
'user': person, 'user': person,
} }

View File

@ -1147,6 +1147,7 @@ markers = [
"model_softwareversion: Selects tests for model Software Version.", "model_softwareversion: Selects tests for model Software Version.",
"model_ticketbase: Selects tests for model Ticket Base.", "model_ticketbase: Selects tests for model Ticket Base.",
"model_ticketcategory: Select all ticket category tests.", "model_ticketcategory: Select all ticket category tests.",
"model_ticketcommentbase: Select all ticket Comment.",
"model_ticketcommentcategory: Select all ticket comment category tests.", "model_ticketcommentcategory: Select all ticket comment category tests.",
"models: Selects all models tests.", "models: Selects all models tests.",
"model_tenant: Select all Tentant model tests.", "model_tenant: Select all Tentant model tests.",