refactor(core): Update Test Suite for TicketBase model

ref: #871 closes #861
This commit is contained in:
2025-07-18 19:33:53 +09:30
parent cf06783aec
commit 4ffbf81b71
12 changed files with 111 additions and 184 deletions

View File

@ -184,7 +184,10 @@ class APIFieldsTestCases:
view_team.delete() view_team.delete()
request.cls.view_user.delete() try:
request.cls.view_user.delete()
except django.db.models.deletion.ProtectedError:
pass
del request.cls.kwargs_create_item del request.cls.kwargs_create_item

View File

@ -48,7 +48,7 @@ class TicketBase(
save_model_history: bool = False save_model_history: bool = False
url_model_name = 'ticket' url_model_name = 'ticketbase'
class Ticket_ExternalSystem(models.IntegerChoices): # <null|github|gitlab> class Ticket_ExternalSystem(models.IntegerChoices): # <null|github|gitlab>
GITHUB = TicketValues.ExternalSystem._GITHUB_INT, TicketValues.ExternalSystem._GITHUB_VALUE GITHUB = TicketValues.ExternalSystem._GITHUB_INT, TicketValues.ExternalSystem._GITHUB_VALUE
@ -831,6 +831,35 @@ class TicketBase(
return related_model return related_model
def get_url_kwargs(self, many = False) -> dict:
"""Get URL Kwargs
Fecth the kwargs required for building a models URL using the reverse
method.
**Note:** It's advisable that if you override this function, that you
call it's super, so as not to duplicate code. That way each override
builds up[on the parent `get_url_kwargs` function.
Returns:
dict: Kwargs required for reverse function to build a models URL.
"""
kwargs = super().get_url_kwargs( many = many )
if self._is_submodel:
del kwargs['model_name']
kwargs.update({
'ticket_type': str(self._meta.sub_model_type),
})
return kwargs
def create_action_comment(self) -> None: def create_action_comment(self) -> None:
from core.models.ticket_comment_action import TicketCommentAction from core.models.ticket_comment_action import TicketCommentAction

View File

@ -243,7 +243,7 @@ class TicketBaseMetadataInheritedCases(
kwargs_create_item_diff_org: dict = {} kwargs_create_item_diff_org: dict = {}
url_name = '_api_ticket_sub' url_name = '_api_ticketbase_sub'
@classmethod @classmethod
@ -260,11 +260,11 @@ class TicketBaseMetadataInheritedCases(
} }
self.url_kwargs = { self.url_kwargs = {
'model_name': self.model._meta.sub_model_type 'ticket_type': self.model._meta.sub_model_type
} }
self.url_view_kwargs = { self.url_view_kwargs = {
'model_name': self.model._meta.sub_model_type 'ticket_type': self.model._meta.sub_model_type
} }
super().setUpTestData() super().setUpTestData()
@ -277,7 +277,7 @@ class TicketBaseMetadataTest(
): ):
url_name = '_api_v2_ticket' url_name = '_api_ticketbase'
# def test_method_options_request_detail_data_has_key_urls_back(self): # def test_method_options_request_detail_data_has_key_urls_back(self):

View File

@ -1,133 +0,0 @@
import pytest
from api.tests.functional.test_functional_api_permissions import (
APIPermissionsInheritedCases,
)
@pytest.mark.model_ticketbase
class PermissionsAPITestCases(
APIPermissionsInheritedCases,
):
add_data: dict = {
'title': 'ticket one',
'description': 'sadsa'
}
app_namespace = 'v2'
change_data = {'description': 'device'}
delete_data = {}
kwargs_create_item: dict = {
'title': 'ticket two',
'description': 'sadsa'
}
kwargs_create_item_diff_org: dict = {
'title': 'ticket three',
'description': 'sadsa'
}
url_kwargs: dict = {}
url_name = '_api_v2_ticket'
url_view_kwargs: dict = {}
@pytest.fixture(scope='class')
def opened_by_var_setup(self, request):
request.cls.kwargs_create_item.update({
'opened_by': request.cls.view_user
})
request.cls.kwargs_create_item_diff_org.update({
'opened_by': request.cls.view_user
})
if request.cls.add_data is not None:
request.cls.add_data.update({
'opened_by': request.cls.view_user.pk
})
@pytest.fixture(scope='class', autouse = True)
def class_setup(self, request, django_db_blocker,
model,
var_setup,
prepare,
opened_by_var_setup,
diff_org_model,
create_model,
post_model
):
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 TicketBasePermissionsAPIInheritedCases(
PermissionsAPITestCases,
):
add_data: dict = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
@pytest.fixture(scope='class')
def inherited_var_setup(self, request):
request.cls.url_kwargs.update({
'model_name': self.model._meta.sub_model_type
})
request.cls.url_view_kwargs.update({
'model_name': self.model._meta.sub_model_type
})
@pytest.fixture(scope='class', autouse = True)
def class_setup(self, request, django_db_blocker,
model,
var_setup,
prepare,
opened_by_var_setup,
inherited_var_setup,
diff_org_model,
create_model,
):
pass
@pytest.mark.module_core
class TicketBasePermissionsAPIPyTest(
PermissionsAPITestCases,
):
pass

View File

@ -207,7 +207,10 @@ class TicketBaseSerializerTestCases:
with django_db_blocker.unblock(): with django_db_blocker.unblock():
request.cls.view_user.delete() try:
request.cls.view_user.delete()
except django.db.models.deletion.ProtectedError:
pass
request.cls.other_user.delete() request.cls.other_user.delete()
del request.cls.valid_data del request.cls.valid_data

View File

@ -93,7 +93,8 @@ class ViewSetBase:
) )
self.url_view_kwargs.update({'model_name': self.item._meta.model_name, 'pk': self.item.id }) # self.url_view_kwargs.update({'ticket_type': self.item._meta.sub_model_type, 'pk': self.item.id })
self.url_view_kwargs.update({'pk': self.item.id })
if self.add_data is not None: if self.add_data is not None:
@ -250,7 +251,7 @@ class TicketBaseViewSetInheritedCases(
# kwargs_create_item_diff_org: dict = {} # kwargs_create_item_diff_org: dict = {}
url_name = '_api_ticket_sub' url_name = '_api_ticketbase_sub'
@classmethod @classmethod
@ -267,11 +268,11 @@ class TicketBaseViewSetInheritedCases(
} }
self.url_kwargs = { self.url_kwargs = {
'model_name': self.model._meta.model_name 'ticket_type': self.model._meta.sub_model_type
} }
self.url_view_kwargs = { self.url_view_kwargs = {
'model_name': self.model._meta.model_name 'ticket_type': self.model._meta.sub_model_type
} }
super().setUpTestData() super().setUpTestData()
@ -283,4 +284,4 @@ class TicketBaseViewSetTest(
TestCase, TestCase,
): ):
url_name = '_api_v2_ticket' url_name = '_api_ticketbase'

View File

@ -1,3 +1,4 @@
import django
import pytest import pytest
from rest_framework.relations import Hyperlink from rest_framework.relations import Hyperlink
@ -67,10 +68,10 @@ class APITestCases(
}) })
if request.cls.model._meta.model_name != 'ticketbase': if request.cls.model._meta.sub_model_type != 'ticket':
request.cls.url_view_kwargs.update({ request.cls.url_view_kwargs.update({
'model_name': str(request.cls.model._meta.sub_model_type), 'ticket_type': str(request.cls.model._meta.sub_model_type),
}) })
yield yield
@ -81,15 +82,24 @@ class APITestCases(
parent_ticket.delete() parent_ticket.delete()
project_milestone.delete() try:
project_milestone.delete()
except django.db.models.deletion.ProtectedError:
pass
project.delete() try:
project.delete()
except django.db.models.deletion.ProtectedError:
pass
request.cls.kwargs_create_item['category'].delete() try:
request.cls.kwargs_create_item['category'].delete()
except django.db.models.deletion.ProtectedError:
pass
if 'model_name' in request.cls.url_view_kwargs: if 'ticket_type' in request.cls.url_view_kwargs:
del request.cls.url_view_kwargs['model_name'] del request.cls.url_view_kwargs['ticket_type']
@ -386,7 +396,7 @@ class APITestCases(
'date_closed': '2025-05-12T02:30:02', 'date_closed': '2025-05-12T02:30:02',
} }
url_ns_name = '_api_v2_ticket' url_ns_name = '_api_ticketbase'
"""Url namespace (optional, if not required) and url name""" """Url namespace (optional, if not required) and url name"""
@ -411,7 +421,7 @@ class TicketBaseAPIInheritedCases(
model = None model = None
url_ns_name = '_api_ticket_sub' url_ns_name = '_api_ticketbase_sub'
@pytest.mark.module_core @pytest.mark.module_core

View File

@ -36,7 +36,7 @@ class TicketBaseModelTestCases(
}, },
'url_model_name': { 'url_model_name': {
'type': str, 'type': str,
'value': 'ticket' 'value': 'ticketbase'
}, },
} }
@ -487,8 +487,12 @@ class TicketBaseModelTestCases(
model_ticketcommentbase, kwargs_ticketcommentbase model_ticketcommentbase, kwargs_ticketcommentbase
): ):
kwargs = kwargs_ticketcommentbase.copy()
del kwargs['ticket']
comment = model_ticketcommentbase.objects.create( comment = model_ticketcommentbase.objects.create(
**kwargs_ticketcommentbase, **kwargs,
ticket = ticket, ticket = ticket,
) )

View File

@ -45,7 +45,7 @@ class ViewsetTestCases(
if self.model != TicketBase: if self.model != TicketBase:
self.kwargs = { self.kwargs = {
'model_name': self.model._meta.model_name 'ticket_type': self.model._meta.sub_model_type
} }
self.viewset.kwargs = self.kwargs self.viewset.kwargs = self.kwargs
@ -73,7 +73,7 @@ class ViewsetTestCases(
view_set = self.viewset() view_set = self.viewset()
assert view_set.model_kwarg == 'model_name' assert view_set.model_kwarg == 'ticket_type'
@ -88,7 +88,7 @@ class TicketBaseViewsetInheritedCases(
model: str = None model: str = None
"""name of the model to test""" """name of the model to test"""
route_name = 'v2:_api_ticket_sub' route_name = 'v2:_api_ticketbase_sub'
@pytest.mark.module_core @pytest.mark.module_core
@ -97,6 +97,6 @@ class TicketBaseViewsetTest(
TestCase, TestCase,
): ):
route_name = 'v2:_api_v2_ticket' route_name = 'v2:_api_ticketbase'
viewset = NoDocsViewSet viewset = NoDocsViewSet

View File

@ -21,7 +21,7 @@ for model in apps.get_models():
if issubclass(model, ticket.TicketBase): if issubclass(model, ticket.TicketBase):
ticket_type_names += model._meta.model_name + '|' ticket_type_names += model._meta.sub_model_type + '|'
if issubclass(model, ticket_comment.TicketCommentBase): if issubclass(model, ticket_comment.TicketCommentBase):
@ -48,16 +48,12 @@ router.register(
router.register( router.register(
prefix=f'ticket', viewset = ticket.ViewSet, prefix=f'ticket', viewset = ticket.NoDocsViewSet,
feature_flag = '2025-00006', basename = '_api_ticket' feature_flag = '2025-00006', basename = '_api_ticketbase'
) )
router.register( router.register(
prefix=f'ticket/(?P<model_name>[{ticket_type_names}]+)', viewset = ticket.ViewSet, prefix=f'ticket/(?P<ticket_type>[{ticket_type_names}]+)', viewset = ticket.ViewSet,
feature_flag = '2025-00006', basename = '_api_ticket_sub' feature_flag = '2025-00006', basename = '_api_ticketbase_sub'
)
router.register(
prefix = 'ticket', viewset = ticket.NoDocsViewSet,
basename = '_api_v2_ticket'
) )
router.register( router.register(
prefix = 'ticket/(?P<ticket_id>[0-9]+)/comment', viewset = ticket_comment.NoDocsViewSet, prefix = 'ticket/(?P<ticket_id>[0-9]+)/comment', viewset = ticket_comment.NoDocsViewSet,

View File

@ -29,7 +29,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
serializer_name = 'ticket' serializer_name = 'ticket'
if model._meta.model_name != 'ticketbase': if model._meta.sub_model_type != 'ticket':
serializer_name += '_' + model._meta.sub_model_type serializer_name += '_' + model._meta.sub_model_type
@ -53,7 +53,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
description='.', description='.',
parameters = [ parameters = [
OpenApiParameter( OpenApiParameter(
name = 'model_name', name = 'ticket_type',
description = 'Enter the Ticket type. This is the name of the Ticket sub-model.', description = 'Enter the Ticket type. This is the name of the Ticket sub-model.',
location = OpenApiParameter.PATH, location = OpenApiParameter.PATH,
type = str, type = str,
@ -94,7 +94,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
description = '.', description = '.',
parameters =[ parameters =[
OpenApiParameter( OpenApiParameter(
name = 'model_name', name = 'ticket_type',
description = 'Enter the ticket type. This is the name of the Ticket sub-model.', description = 'Enter the ticket type. This is the name of the Ticket sub-model.',
location = OpenApiParameter.PATH, location = OpenApiParameter.PATH,
type = str, type = str,
@ -118,7 +118,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
description='.', description='.',
parameters = [ parameters = [
OpenApiParameter( OpenApiParameter(
name = 'model_name', name = 'ticket_type',
description = 'Enter the ticket type. This is the name of the Ticket sub-model.', description = 'Enter the ticket type. This is the name of the Ticket sub-model.',
location = OpenApiParameter.PATH, location = OpenApiParameter.PATH,
type = str, type = str,
@ -150,7 +150,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
description='.', description='.',
parameters = [ parameters = [
OpenApiParameter( OpenApiParameter(
name = 'model_name', name = 'ticket_type',
description = 'Enter the ticket type. This is the name of the Ticket sub-model.', description = 'Enter the ticket type. This is the name of the Ticket sub-model.',
location = OpenApiParameter.PATH, location = OpenApiParameter.PATH,
type = str, type = str,
@ -183,7 +183,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
description = '.', description = '.',
parameters = [ parameters = [
OpenApiParameter( OpenApiParameter(
name = 'tickets_model', name = 'tickets_type',
description = 'Enter the ticket type. This is the name of the Ticket sub-model.', description = 'Enter the ticket type. This is the name of the Ticket sub-model.',
location = OpenApiParameter.PATH, location = OpenApiParameter.PATH,
type = str, type = str,
@ -238,7 +238,7 @@ class ViewSet( SubModelViewSet ):
'is_deleted' 'is_deleted'
] ]
model_kwarg = 'model_name' model_kwarg = 'ticket_type'
search_fields = [ search_fields = [
'title', 'title',
@ -257,10 +257,10 @@ class ViewSet( SubModelViewSet ):
): ):
self.back_url = reverse( self.back_url = reverse(
viewname = '_api_ticket_sub-list', viewname = '_api_ticketbase_sub-list',
request = self.request, request = self.request,
kwargs = { kwargs = {
'model_name': self.kwargs[self.model_kwarg], 'ticket_type': self.kwargs[self.model_kwarg],
} }
) )

View File

@ -1,6 +1,8 @@
import datetime import datetime
from django.core.exceptions import ValidationError, ObjectDoesNotExist
import pytest import pytest
import random
from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.db import models from django.db import models
@ -21,9 +23,17 @@ def model_kwarg_data():
for field, value in model_kwargs.items(): for field, value in model_kwargs.items():
is_unique_together_field = False
if not hasattr(getattr(model, field), 'field'): if not hasattr(getattr(model, field), 'field'):
continue continue
for unique_field in getattr(model, field).field.model._meta.unique_together:
if field in unique_field and getattr(model, field).field.choices is None:
is_unique_together_field = True
if isinstance(getattr(model, field).field, models.ManyToManyField): if isinstance(getattr(model, field).field, models.ManyToManyField):
if isinstance(value, list): if isinstance(value, list):
@ -59,7 +69,10 @@ def model_kwarg_data():
continue continue
elif( elif(
getattr(model, field).field.unique (
getattr(model, field).field.unique
or is_unique_together_field
)
and not isinstance(getattr(model, field).field, models.UUIDField) and not isinstance(getattr(model, field).field, models.UUIDField)
and not isinstance(getattr(model, field).field, models.ForeignKey) and not isinstance(getattr(model, field).field, models.ForeignKey)
@ -69,7 +82,8 @@ def model_kwarg_data():
if isinstance(getattr(model, field).field, models.IntegerField): if isinstance(getattr(model, field).field, models.IntegerField):
value = str(random_str)[( len(random_str) - 13 ):] # value = str(random_str)[( len(random_str) - 13 ):]
value = random.randint(1,999999)
elif isinstance(getattr(model, field).field, models.EmailField): elif isinstance(getattr(model, field).field, models.EmailField):
@ -110,9 +124,9 @@ def model_kwarg_data():
no_modified_in_kwargs = kwargs.copy() no_modified_in_kwargs = kwargs.copy()
del no_modified_in_kwargs['modified'] del no_modified_in_kwargs['modified']
instance = model.objects.get( instance = model.objects.get(
**no_modified_in_kwargs **no_modified_in_kwargs
) )
for field, values in many_field.items(): for field, values in many_field.items():