Merge pull request #938 from nofusscomputing/project_management-refactor-tests

This commit is contained in:
Jon
2025-08-04 17:25:17 +09:30
committed by GitHub
52 changed files with 1754 additions and 2396 deletions

View File

@ -262,6 +262,15 @@ def pytest_generate_tests(metafunc):
if len(arg_values) > 0: if len(arg_values) > 0:
# Get the test method
test_func = getattr(metafunc.cls, metafunc.definition.name, None)
# Remove previous xfail mark if present
if test_func and hasattr(test_func, 'pytestmark'):
test_func.pytestmark = [
mark for mark in test_func.pytestmark if mark.name != 'xfail'
]
metafunc.parametrize( metafunc.parametrize(
argnames = [ argnames = [
*fixture_parameters *fixture_parameters

View File

@ -262,7 +262,13 @@ class TicketBaseModelTestCases(
ticket = model.objects.create( **kwargs ) ticket = model.objects.create( **kwargs )
project_one = model_project.objects.create( **kwargs_project ) kwargs_proj = kwargs_project.copy()
team_members = kwargs_proj['team_members']
del kwargs_proj['team_members']
del kwargs_proj['code']
project_one = model_project.objects.create( **kwargs_proj )
project_one.team_members.add( team_members[0] )
kwargs = kwargs_projectmilestone kwargs = kwargs_projectmilestone
@ -271,7 +277,12 @@ class TicketBaseModelTestCases(
kwargs = kwargs_project kwargs = kwargs_project
kwargs['name'] = 'project_two' kwargs['name'] = 'project_two'
team_members = kwargs['team_members']
del kwargs['team_members']
del kwargs['code']
project_two = model_project.objects.create( **kwargs ) project_two = model_project.objects.create( **kwargs )
project_two.team_members.add( team_members[0] )
kwargs = kwargs_projectmilestone kwargs = kwargs_projectmilestone
kwargs['name'] = 'two' kwargs['name'] = 'two'

View File

@ -148,7 +148,7 @@ class TicketCommentBaseModelTestCases(
"is_closed": { "is_closed": {
'blank': False, 'blank': False,
'default': False, 'default': False,
'field_type': models.fields.IntegerField, 'field_type': models.fields.BooleanField,
'null': False, 'null': False,
'unique': False, 'unique': False,
}, },

View File

@ -54,7 +54,7 @@ class GitGroupModelTestCases(
'name': { 'name': {
'blank': False, 'blank': False,
'default': models.fields.NOT_PROVIDED, 'default': models.fields.NOT_PROVIDED,
'field_type': models.IntegerField, 'field_type': models.CharField,
'length': 80, 'length': 80,
'null': False, 'null': False,
'unique': False, 'unique': False,
@ -62,7 +62,7 @@ class GitGroupModelTestCases(
'path': { 'path': {
'blank': False, 'blank': False,
'default': models.fields.NOT_PROVIDED, 'default': models.fields.NOT_PROVIDED,
'field_type': models.IntegerField, 'field_type': models.CharField,
'length': 80, 'length': 80,
'null': False, 'null': False,
'unique': False, 'unique': False,
@ -70,7 +70,7 @@ class GitGroupModelTestCases(
'description': { 'description': {
'blank': True, 'blank': True,
'default': models.fields.NOT_PROVIDED, 'default': models.fields.NOT_PROVIDED,
'field_type': models.IntegerField, 'field_type': models.TextField,
'max_length': 80, 'max_length': 80,
'null': True, 'null': True,
'unique': False, 'unique': False,

View File

@ -25,7 +25,7 @@ class GitLabRepositoryBaseModelTestCases(
'visibility': { 'visibility': {
'blank': False, 'blank': False,
'default': models.NOT_PROVIDED, 'default': models.NOT_PROVIDED,
'field_type': models.BooleanField, 'field_type': models.IntegerField,
'null': False, 'null': False,
'unique': False, 'unique': False,
} }

View File

@ -53,7 +53,7 @@ class SoftwareEnableFeatureFlagModelTestCases(
'enabled': { 'enabled': {
'blank': False, 'blank': False,
'default': False, 'default': False,
'field_type': models.IntegerField, 'field_type': models.BooleanField,
'null': False, 'null': False,
'unique': False, 'unique': False,
}, },

View File

@ -0,0 +1,25 @@
import pytest
@pytest.fixture( scope = 'class')
def model(model_project):
yield model_project
@pytest.fixture( scope = 'class', autouse = True)
def model_kwargs(request, kwargs_project):
request.cls.kwargs_create_item = kwargs_project.copy()
yield kwargs_project.copy()
if hasattr(request.cls, 'kwargs_create_item'):
del request.cls.kwargs_create_item
@pytest.fixture( scope = 'class')
def model_serializer(serializer_project):
yield serializer_project

View File

@ -0,0 +1,217 @@
import pytest
from django.db import models
from rest_framework.relations import Hyperlink
from api.tests.functional.test_functional_api_fields import (
APIFieldsInheritedCases,
)
@pytest.mark.model_project
class ProjectAPITestCases(
APIFieldsInheritedCases,
):
@pytest.fixture( scope = 'class')
def second_model(self, request, django_db_blocker,
model, model_kwargs,
model_team, kwargs_team
):
item = None
with django_db_blocker.unblock():
kwargs_many_to_many = {}
kwargs = {}
for key, value in model_kwargs.items():
field = model._meta.get_field(key)
if isinstance(field, models.ManyToManyField):
kwargs_many_to_many.update({
key: value
})
else:
kwargs.update({
key: value
})
# # Switch model fields so all fields can be checked
# kwargs_many_to_many.update({ 'devices': kwargs_many_to_many['nodes']})
# del kwargs_many_to_many['nodes']
# # del kwargs_many_to_many['target_team']
# kwargs.update({ 'parent_project': self.item})
del kwargs['manager_user']
manager_team = model_team.objects.create( **kwargs_team )
kwargs['manager_team'] = manager_team
kwargs['external_ref'] = 1
kwargs['external_system'] = 1
kwargs['name'] = 'pro two'
del kwargs['code']
item_two = model.objects.create(
**kwargs
)
for key, value in kwargs_many_to_many.items():
field = getattr(item_two, key)
for entry in value:
field.add(entry)
request.cls.item_two = item_two
yield item_two
with django_db_blocker.unblock():
item_two.delete()
manager_team.delete()
del request.cls.item_two
@pytest.fixture( scope = 'class', autouse = True)
def class_setup(self,
create_model,
second_model,
make_request,
):
pass
@property
def parameterized_api_fields(self):
return {
'model_notes': {
'expected': models.NOT_PROVIDED
},
'external_ref': {
'expected': int
},
'external_system': {
'expected': int
},
'name': {
'expected': str
},
'description': {
'expected': str
},
'priority': {
'expected': int
},
'state': {
'expected': dict
},
'state.id': {
'expected': int
},
'state.display_name': {
'expected': str
},
'state.url': {
'expected': Hyperlink
},
'project_type': {
'expected': dict
},
'project_type.id': {
'expected': int
},
'project_type.display_name': {
'expected': str
},
'project_type.url': {
'expected': Hyperlink
},
'code': {
'expected': str
},
'planned_start_date': {
'expected': str
},
'planned_finish_date': {
'expected': str
},
'real_finish_date': {
'expected': str
},
'manager_user': {
'expected': dict
},
'manager_user.id': {
'expected': int
},
'manager_user.display_name': {
'expected': str
},
'manager_user.url': {
'expected': Hyperlink
},
'manager_team': {
'expected': dict
},
'manager_team.id': {
'expected': int
},
'manager_team.display_name': {
'expected': str
},
'manager_team.url': {
'expected': str
},
'team_members': {
'expected': list
},
'team_members.0.id': {
'expected': int
},
'team_members.0.display_name': {
'expected': str
},
'team_members.0.url': {
'expected': Hyperlink
},
'is_deleted': {
'expected': bool
},
'modified': {
'expected': str
}
}
class ProjectAPIInheritedCases(
ProjectAPITestCases,
):
pass
@pytest.mark.module_project_management
class ProjectAPIPyTest(
ProjectAPITestCases,
):
pass

View File

@ -3,15 +3,12 @@ import pytest
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse from django.test import TestCase
from django.test import Client, TestCase
from access.models.tenant import Tenant as Organization from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from api.tests.abstract.api_permissions_viewset import APIPermissions
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
from project_management.models.projects import Project from project_management.models.projects import Project
@ -22,6 +19,7 @@ User = django.contrib.auth.get_user_model()
@pytest.mark.module_project_management
class ViewSetBase: class ViewSetBase:
model = Project model = Project
@ -247,69 +245,7 @@ class ViewSetBase:
class ProjectPermissionsAPI(ViewSetBase, APIPermissions, TestCase): @pytest.mark.model_project
def test_add_has_permission_no_import_fields(self):
""" Check correct permission for add
Attempt to add as user with permission
"""
client = Client()
if self.url_kwargs:
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
else:
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
client.force_login(self.add_user)
response = client.post(url, data=self.add_data_import_fields)
assert (
response.status_code == 201
and response.data['external_ref'] is None
and response.data['external_system'] is None
)
def test_add_has_permission_import_fields(self):
""" Check correct permission for add
Attempt to add as user with permission
"""
client = Client()
if self.url_kwargs:
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
else:
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
client.force_login(self.import_user)
response = client.post(url, data=self.add_data_import_fields)
assert (
response.status_code == 201
and response.data['external_ref'] == 1
and response.data['external_system'] == int(Project.Ticket_ExternalSystem.CUSTOM_1)
)
class ProjectViewSet(ViewSetBase, SerializersTestCases, TestCase):
pass
class ProjectMetadata( class ProjectMetadata(
ViewSetBase, ViewSetBase,
MetaDataNavigationEntriesFunctional, MetaDataNavigationEntriesFunctional,

View File

@ -0,0 +1,28 @@
import pytest
from core.tests.functional.centurion_abstract.test_functional_centurion_abstract_model import (
CenturionAbstractModelInheritedCases
)
@pytest.mark.model_project
class ProjectModelTestCases(
CenturionAbstractModelInheritedCases
):
pass
class ProjectModelInheritedCases(
ProjectModelTestCases,
):
pass
@pytest.mark.module_project_management
class ProjectModelPyTest(
ProjectModelTestCases,
):
pass

View File

@ -1,135 +0,0 @@
import pytest
from django.test import TestCase
from rest_framework.exceptions import ValidationError
from access.models.tenant import Tenant as Organization
from project_management.serializers.project import (
Project,
ProjectImportSerializer,
ProjectModelSerializer
)
class ProjectValidationAPI(
TestCase,
):
model = Project
@classmethod
def setUpTestData(self):
"""Setup Test
1. Create an org
2. Create an item
"""
organization = Organization.objects.create(name='test_org')
self.organization = organization
def test_serializer_validation_can_create(self):
"""Serializer Validation Check
Ensure that a valid item can be creates
"""
serializer = ProjectModelSerializer(data={
"organization": self.organization.id,
"name": 'a project'
})
assert serializer.is_valid(raise_exception = True)
def test_serializer_validation_no_name(self):
"""Serializer Validation Check
Ensure that if creating and no name is provided a validation error occurs
"""
with pytest.raises(ValidationError) as err:
serializer = ProjectModelSerializer(
data={
"organization": self.organization.id,
},
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['name'][0] == 'required'
def test_serializer_validation_external_ref_not_import_user(self):
"""Serializer Validation Check
Ensure that if creating by user who is not import user, they can't edit
fields external_ref and external_system.
"""
class MockView:
is_import_user = False
serializer = ProjectModelSerializer(
context = {
'view': MockView
},
data={
"name": 'project name',
"organization": self.organization.id,
'external_ref': 1,
'external_system': int(Project.Ticket_ExternalSystem.CUSTOM_1)
},
)
serializer.is_valid(raise_exception = True)
serializer.save()
assert serializer.instance.external_ref is None and serializer.instance.external_system is None
def test_serializer_validation_external_ref_is_import_user(self):
"""Serializer Validation Check
Ensure that if creating by user who import user, they can edit
fields external_ref and external_system.
"""
class MockView:
is_import_user = True
serializer = ProjectImportSerializer(
context = {
'view': MockView
},
data={
"name": 'another project',
"organization": self.organization.id,
"external_ref": 1,
"external_system": int(Project.Ticket_ExternalSystem.CUSTOM_1)
},
)
serializer.is_valid(raise_exception = True)
serializer.save()
assert (
serializer.instance.external_ref == 1 and
serializer.instance.external_system == int(Project.Ticket_ExternalSystem.CUSTOM_1)
)

View File

@ -0,0 +1,25 @@
import pytest
@pytest.fixture( scope = 'class')
def model(model_projectmilestone):
yield model_projectmilestone
@pytest.fixture( scope = 'class', autouse = True)
def model_kwargs(request, kwargs_projectmilestone):
request.cls.kwargs_create_item = kwargs_projectmilestone.copy()
yield kwargs_projectmilestone.copy()
if hasattr(request.cls, 'kwargs_create_item'):
del request.cls.kwargs_create_item
@pytest.fixture( scope = 'class')
def model_serializer(serializer_projectmilestone):
yield serializer_projectmilestone

View File

@ -0,0 +1,66 @@
import pytest
from django.db import models
from rest_framework.relations import Hyperlink
from api.tests.functional.test_functional_api_fields import (
APIFieldsInheritedCases,
)
@pytest.mark.model_projectmilestone
class ProjectMilestoneAPITestCases(
APIFieldsInheritedCases,
):
@property
def parameterized_api_fields(self):
return {
'model_notes': {
'expected': models.NOT_PROVIDED
},
'name': {
'expected': str
},
'start_date': {
'expected': str
},
'finish_date': {
'expected': str
},
'project': {
'expected': dict
},
'project.id': {
'expected': int
},
'project.display_name': {
'expected': str
},
'project.url': {
'expected': Hyperlink
},
'modified': {
'expected': str
}
}
class ProjectMilestoneAPIInheritedCases(
ProjectMilestoneAPITestCases,
):
pass
@pytest.mark.module_project_management
class ProjectMilestoneAPIPyTest(
ProjectMilestoneAPITestCases,
):
pass

View File

@ -9,8 +9,6 @@ from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from api.tests.abstract.api_permissions_viewset import APIPermissions
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
from project_management.models.project_milestone import Project, ProjectMilestone from project_management.models.project_milestone import Project, ProjectMilestone
@ -19,6 +17,7 @@ User = django.contrib.auth.get_user_model()
@pytest.mark.model_projectmilestone
class ViewSetBase: class ViewSetBase:
model = ProjectMilestone model = ProjectMilestone
@ -202,29 +201,7 @@ class ViewSetBase:
class ProjectMilestonePermissionsAPI(ViewSetBase, APIPermissions, TestCase): @pytest.mark.module_project_management
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 ProjectMilestoneViewSet(ViewSetBase, SerializersTestCases, TestCase):
pass
class ProjectMilestoneMetadata( class ProjectMilestoneMetadata(
ViewSetBase, ViewSetBase,
MetadataAttributesFunctional, MetadataAttributesFunctional,

View File

@ -0,0 +1,28 @@
import pytest
from core.tests.functional.centurion_abstract.test_functional_centurion_abstract_model import (
CenturionAbstractModelInheritedCases
)
@pytest.mark.model_project
class ProjectMilestoneModelTestCases(
CenturionAbstractModelInheritedCases
):
pass
class ProjectMilestoneModelInheritedCases(
ProjectMilestoneModelTestCases,
):
pass
@pytest.mark.module_project_management
class ProjectMilestoneModelPyTest(
ProjectMilestoneModelTestCases,
):
pass

View File

@ -1,126 +0,0 @@
import pytest
from django.test import TestCase
from rest_framework.exceptions import ValidationError
from access.models.tenant import Tenant as Organization
from project_management.serializers.project_milestone import (
Project,
ProjectMilestone,
ProjectMilestoneModelSerializer
)
class ProjectMilestoneValidationAPI(
TestCase,
):
model = ProjectMilestone
@classmethod
def setUpTestData(self):
"""Setup Test
1. Create an org
2. Create an item
"""
organization = Organization.objects.create(name='test_org')
self.organization = organization
self.project = Project.objects.create(
name = 'proj mile',
organization = self.organization
)
def test_serializer_validation_can_create(self):
"""Serializer Validation Check
Ensure that a valid item can be creates
"""
# self._kwargs['context']['view'].kwargs['project_id'])
class MockView:
kwargs = {
'project_id': self.project.id
}
serializer = ProjectMilestoneModelSerializer(
context = {
'view': MockView
},
data={
"organization": self.organization.id,
"name": 'a milestone',
}
)
assert serializer.is_valid(raise_exception = True)
def test_serializer_validation_no_name(self):
"""Serializer Validation Check
Ensure that if creating and no name is provided a validation error occurs
"""
class MockView:
kwargs = {
'project_id': self.project.id
}
with pytest.raises(ValidationError) as err:
serializer = ProjectMilestoneModelSerializer(
context = {
'view': MockView
},
data={
"organization": self.organization.id,
},
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['name'][0] == 'required'
# def test_serializer_validation_no_project(self):
# """Serializer Validation Check
# Ensure that if creating and no name is provided a validation error occurs
# """
# class MockView:
# kwargs = {
# 'project_id': self.project.id
# }
# with pytest.raises(ValidationError) as err:
# serializer = ProjectMilestoneModelSerializer(
# context = {
# 'view': MockView
# },
# data={
# "organization": self.organization.id,
# "name": 'a milestone',
# },
# )
# serializer.is_valid(raise_exception = True)
# assert err.value.get_codes()['project'][0] == 'required'

View File

@ -0,0 +1,25 @@
import pytest
@pytest.fixture( scope = 'class')
def model(model_projectstate):
yield model_projectstate
@pytest.fixture( scope = 'class', autouse = True)
def model_kwargs(request, kwargs_projectstate):
request.cls.kwargs_create_item = kwargs_projectstate.copy()
yield kwargs_projectstate.copy()
if hasattr(request.cls, 'kwargs_create_item'):
del request.cls.kwargs_create_item
@pytest.fixture( scope = 'class')
def model_serializer(serializer_projectstate):
yield serializer_projectstate

View File

@ -0,0 +1,138 @@
import pytest
from api.tests.functional.test_functional_api_fields import (
APIFieldsInheritedCases,
)
@pytest.mark.model_projectmilestone
class ProjectStateAPITestCases(
APIFieldsInheritedCases,
):
# @pytest.fixture( scope = 'class')
# def second_model(self, request, django_db_blocker,
# model, model_kwargs,
# model_team, kwargs_team
# ):
# item = None
# with django_db_blocker.unblock():
# kwargs_many_to_many = {}
# kwargs = {}
# for key, value in model_kwargs.items():
# field = model._meta.get_field(key)
# if isinstance(field, models.ManyToManyField):
# kwargs_many_to_many.update({
# key: value
# })
# else:
# kwargs.update({
# key: value
# })
# # # Switch model fields so all fields can be checked
# # kwargs_many_to_many.update({ 'devices': kwargs_many_to_many['nodes']})
# # del kwargs_many_to_many['nodes']
# # # del kwargs_many_to_many['target_team']
# # kwargs.update({ 'parent_projectmilestone': self.item})
# del kwargs['manager_user']
# manager_team = model_team.objects.create( **kwargs_team )
# kwargs['manager_team'] = manager_team
# kwargs['external_ref'] = 1
# kwargs['external_system'] = 1
# kwargs['name'] = 'pro two'
# del kwargs['code']
# item_two = model.objects.create(
# **kwargs
# )
# for key, value in kwargs_many_to_many.items():
# field = getattr(item_two, key)
# for entry in value:
# field.add(entry)
# request.cls.item_two = item_two
# yield item_two
# with django_db_blocker.unblock():
# item_two.delete()
# manager_team.delete()
# del request.cls.item_two
# @pytest.fixture( scope = 'class', autouse = True)
# def class_setup(self,
# create_model,
# second_model,
# make_request,
# ):
# pass
@property
def parameterized_api_fields(self):
return {
'name': {
'expected': str
},
'runbook': {
'expected': dict
},
'runbook.id': {
'expected': int
},
'runbook.display_name': {
'expected': str
},
'runbook.url': {
'expected': str
},
'is_completed': {
'expected': bool
},
'modified': {
'expected': str
}
}
class ProjectStateAPIInheritedCases(
ProjectStateAPITestCases,
):
pass
@pytest.mark.module_project_management
class ProjectStateAPIPyTest(
ProjectStateAPITestCases,
):
pass

View File

@ -9,8 +9,6 @@ from access.models.tenant import Tenant as Organization
from access.models.team import Team from access.models.team import Team
from access.models.team_user import TeamUsers from access.models.team_user import TeamUsers
from api.tests.abstract.api_permissions_viewset import APIPermissions
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
from project_management.models.project_states import ProjectState from project_management.models.project_states import ProjectState
@ -21,6 +19,7 @@ User = django.contrib.auth.get_user_model()
@pytest.mark.model_projectstate
class ViewSetBase: class ViewSetBase:
model = ProjectState model = ProjectState
@ -216,18 +215,7 @@ class ViewSetBase:
class ProjectStatePermissionsAPI(ViewSetBase, APIPermissions, TestCase): @pytest.mark.module_project_management
pass
class ProjectStateViewSet(ViewSetBase, SerializersTestCases, TestCase):
pass
class ProjectStateMetadata( class ProjectStateMetadata(
ViewSetBase, ViewSetBase,
MetadataAttributesFunctional, MetadataAttributesFunctional,

View File

@ -0,0 +1,28 @@
import pytest
from core.tests.functional.centurion_abstract.test_functional_centurion_abstract_model import (
CenturionAbstractModelInheritedCases
)
@pytest.mark.model_projectstate
class ProjectStateModelTestCases(
CenturionAbstractModelInheritedCases
):
pass
class ProjectStateModelInheritedCases(
ProjectStateModelTestCases,
):
pass
@pytest.mark.module_project_management
class ProjectStateModelPyTest(
ProjectStateModelTestCases,
):
pass

View File

@ -1,83 +0,0 @@
import pytest
from django.test import TestCase
from rest_framework.exceptions import ValidationError
from access.models.tenant import Tenant as Organization
from centurion.tests.abstract.mock_view import MockView, User
from project_management.serializers.project_states import (
ProjectState,
ProjectStateModelSerializer
)
class ProjectStateValidationAPI(
TestCase,
):
model = ProjectState
@classmethod
def setUpTestData(self):
"""Setup Test
1. Create an org
2. Create an item
"""
organization = Organization.objects.create(name='test_org')
self.user = User.objects.create_user(username="test_user_view", password="password")
self.organization = organization
self.mock_view = MockView( user = self.user )
def test_serializer_validation_can_create(self):
"""Serializer Validation Check
Ensure that a valid item can be creates
"""
serializer = ProjectStateModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
"organization": self.organization.id,
"name": 'a project'
}
)
assert serializer.is_valid(raise_exception = True)
def test_serializer_validation_no_name(self):
"""Serializer Validation Check
Ensure that if creating and no name is provided a validation error occurs
"""
with pytest.raises(ValidationError) as err:
serializer = ProjectStateModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
"organization": self.organization.id,
},
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['name'][0] == 'required'

View File

@ -0,0 +1,25 @@
import pytest
@pytest.fixture( scope = 'class')
def model(model_projecttype):
yield model_projecttype
@pytest.fixture( scope = 'class', autouse = True)
def model_kwargs(request, kwargs_projecttype):
request.cls.kwargs_create_item = kwargs_projecttype.copy()
yield kwargs_projecttype.copy()
if hasattr(request.cls, 'kwargs_create_item'):
del request.cls.kwargs_create_item
@pytest.fixture( scope = 'class')
def model_serializer(serializer_projecttype):
yield serializer_projecttype

View File

@ -0,0 +1,53 @@
import pytest
from api.tests.functional.test_functional_api_fields import (
APIFieldsInheritedCases,
)
@pytest.mark.model_projecttype
class ProjectTypeAPITestCases(
APIFieldsInheritedCases,
):
@property
def parameterized_api_fields(self):
return {
'name': {
'expected': str
},
'runbook': {
'expected': dict
},
'runbook.id': {
'expected': int
},
'runbook.display_name': {
'expected': str
},
'runbook.url': {
'expected': str
},
'modified': {
'expected': str
}
}
class ProjectTypeAPIInheritedCases(
ProjectTypeAPITestCases,
):
pass
@pytest.mark.module_project_management
class ProjectTypeAPIPyTest(
ProjectTypeAPITestCases,
):
pass

View File

@ -21,6 +21,7 @@ User = django.contrib.auth.get_user_model()
@pytest.mark.model_projecttype
class ViewSetBase: class ViewSetBase:
model = ProjectType model = ProjectType
@ -215,18 +216,7 @@ class ViewSetBase:
class ProjectTypePermissionsAPI(ViewSetBase, APIPermissions, TestCase): @pytest.mark.module_project_management
pass
class ProjectTypeViewSet(ViewSetBase, SerializersTestCases, TestCase):
pass
class ProjectTypeMetadata( class ProjectTypeMetadata(
ViewSetBase, ViewSetBase,
MetadataAttributesFunctional, MetadataAttributesFunctional,

View File

@ -0,0 +1,28 @@
import pytest
from core.tests.functional.centurion_abstract.test_functional_centurion_abstract_model import (
CenturionAbstractModelInheritedCases
)
@pytest.mark.model_projecttype
class ProjectTypeModelTestCases(
CenturionAbstractModelInheritedCases
):
pass
class ProjectTypeModelInheritedCases(
ProjectTypeModelTestCases,
):
pass
@pytest.mark.module_project_management
class ProjectTypeModelPyTest(
ProjectTypeModelTestCases,
):
pass

View File

@ -1,83 +0,0 @@
import pytest
from django.test import TestCase
from rest_framework.exceptions import ValidationError
from access.models.tenant import Tenant as Organization
from centurion.tests.abstract.mock_view import MockView, User
from project_management.serializers.project_type import (
ProjectType,
ProjectTypeModelSerializer
)
class ProjectTypeValidationAPI(
TestCase,
):
model = ProjectType
@classmethod
def setUpTestData(self):
"""Setup Test
1. Create an org
2. Create an item
"""
organization = Organization.objects.create(name='test_org')
self.user = User.objects.create_user(username="test_user_view", password="password")
self.organization = organization
self.mock_view = MockView( user = self.user )
def test_serializer_validation_can_create(self):
"""Serializer Validation Check
Ensure that a valid item can be creates
"""
serializer = ProjectTypeModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
"organization": self.organization.id,
"name": 'a project'
}
)
assert serializer.is_valid(raise_exception = True)
def test_serializer_validation_no_name(self):
"""Serializer Validation Check
Ensure that if creating and no name is provided a validation error occurs
"""
with pytest.raises(ValidationError) as err:
serializer = ProjectTypeModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
"organization": self.organization.id,
},
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['name'][0] == 'required'

View File

@ -17,3 +17,9 @@ def model_kwargs(request, kwargs_project):
if hasattr(request.cls, 'kwargs_create_item'): if hasattr(request.cls, 'kwargs_create_item'):
del request.cls.kwargs_create_item del request.cls.kwargs_create_item
@pytest.fixture( scope = 'class')
def model_serializer(serializer_project):
yield serializer_project

View File

@ -1,767 +0,0 @@
import django
import pytest
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse
from django.test import Client, TestCase
from rest_framework.relations import Hyperlink
from access.models.tenant import Tenant as Organization
from access.models.team import Team
from access.models.team_user import TeamUsers
from api.tests.abstract.api_fields import APITenancyObject
from project_management.models.projects import Project, ProjectState, ProjectType
from settings.models.user_settings import UserSettings
User = django.contrib.auth.get_user_model()
@pytest.mark.model_project
@pytest.mark.module_project_management
class ProjectAPI(
TestCase,
APITenancyObject
):
model = Project
@classmethod
def setUpTestData(self):
"""Setup Test
1. Create an organization for user and item
2. Create an item
"""
self.organization = Organization.objects.create(name='test_org')
project_type = ProjectType.objects.create(
organization = self.organization,
name = 'proj type'
)
project_state = ProjectState.objects.create(
organization = self.organization,
name = 'a state'
)
view_permissions = Permission.objects.get(
codename = 'view_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
view_team = Team.objects.create(
team_name = 'view_team',
organization = self.organization,
)
view_team.permissions.set([view_permissions])
self.view_user = User.objects.create_user(username="test_user_view", password="password")
user_settings = UserSettings.objects.get(user = self.view_user)
user_settings.default_organization = self.organization
user_settings.save()
teamuser = TeamUsers.objects.create(
team = view_team,
user = self.view_user
)
self.item = self.model.objects.create(
organization = self.organization,
name = 'one',
state = project_state,
project_type = project_type,
description = 'a note',
manager_user = self.view_user,
manager_team = view_team,
planned_start_date = '2024-01-01 00:01:00',
planned_finish_date = '2024-01-01 00:01:01',
real_start_date = '2024-01-02 00:01:00',
real_finish_date = '2024-01-02 00:01:01',
code = 'acode',
external_ref = 1,
external_system = Project.Ticket_ExternalSystem.CUSTOM_1
)
self.item.team_members.set([ self.view_user ])
self.url_view_kwargs = {'pk': self.item.id}
client = Client()
url = reverse('v2:_api_project-detail', kwargs=self.url_view_kwargs)
client.force_login(self.view_user)
response = client.get(url)
self.api_data = response.data
def test_api_field_exists_estimation_project(self):
""" Test for existance of API Field
This test is a custom test of a test case with the same name.
this model does not have a model_notes_field
estimation_project field must exist
"""
assert 'estimation_project' in self.api_data
def test_api_field_type_estimation_project(self):
""" Test for type for API Field
estimation_project field must be int
"""
assert type(self.api_data['estimation_project']) is int
def test_api_field_exists_duration_project(self):
""" Test for existance of API Field
This test is a custom test of a test case with the same name.
this model does not have a model_notes_field
duration_project field must exist
"""
assert 'duration_project' in self.api_data
def test_api_field_type_duration_project(self):
""" Test for type for API Field
duration_project field must be int
"""
assert type(self.api_data['duration_project']) is int
def test_api_field_exists_completed(self):
""" Test for existance of API Field
This test is a custom test of a test case with the same name.
this model does not have a model_notes_field
model_notes field must exist
"""
assert 'completed' in self.api_data
def test_api_field_type_completed(self):
""" Test for type for API Field
description field must be str
"""
assert type(self.api_data['completed']) is str
def test_api_field_exists_model_notes(self):
""" Test for existance of API Field
This test is a custom test of a test case with the same name.
this model does not have a model_notes_field
model_notes field must exist
"""
assert 'model_notes' not in self.api_data
def test_api_field_type_model_notes(self):
""" Test for type for API Field
This test is a custom test of a test case with the same name.
this model does not have a model_notes_field
model_notes field must be str
"""
assert True
def test_api_field_exists_description(self):
""" Test for existance of API Field
model_notes field must exist
"""
assert 'description' in self.api_data
def test_api_field_type_description(self):
""" Test for type for API Field
description field must be str
"""
assert type(self.api_data['description']) is str
def test_api_field_exists_priority(self):
""" Test for existance of API Field
priority field must exist
"""
assert 'priority' in self.api_data
def test_api_field_type_priority(self):
""" Test for type for API Field
priority field must be int
"""
assert type(self.api_data['priority']) is int
def test_api_field_exists_code(self):
""" Test for existance of API Field
code field must exist
"""
assert 'code' in self.api_data
def test_api_field_type_code(self):
""" Test for type for API Field
code field must be str
"""
assert type(self.api_data['code']) is str
def test_api_field_exists_planned_start_date(self):
""" Test for existance of API Field
planned_start_date field must exist
"""
assert 'planned_start_date' in self.api_data
def test_api_field_type_planned_start_date(self):
""" Test for type for API Field
planned_start_date field must be str
"""
assert type(self.api_data['planned_start_date']) is str
def test_api_field_exists_planned_finish_date(self):
""" Test for existance of API Field
planned_finish_date field must exist
"""
assert 'planned_finish_date' in self.api_data
def test_api_field_type_planned_finish_date(self):
""" Test for type for API Field
planned_finish_date field must be str
"""
assert type(self.api_data['planned_finish_date']) is str
def test_api_field_exists_real_start_date(self):
""" Test for existance of API Field
real_start_date field must exist
"""
assert 'real_start_date' in self.api_data
def test_api_field_type_real_start_date(self):
""" Test for type for API Field
real_start_date field must be str
"""
assert type(self.api_data['real_start_date']) is str
def test_api_field_exists_real_finish_date(self):
""" Test for existance of API Field
real_finish_date field must exist
"""
assert 'real_finish_date' in self.api_data
def test_api_field_type_real_finish_date(self):
""" Test for type for API Field
real_finish_date field must be str
"""
assert type(self.api_data['real_finish_date']) is str
def test_api_field_exists_is_deleted(self):
""" Test for existance of API Field
is_deleted field must exist
"""
assert 'is_deleted' in self.api_data
def test_api_field_type_is_deleted(self):
""" Test for type for API Field
is_deleted field must be bool
"""
assert type(self.api_data['is_deleted']) is bool
def test_api_field_exists_external_ref(self):
""" Test for existance of API Field
external_ref field must exist
"""
assert 'external_ref' in self.api_data
def test_api_field_type_external_ref(self):
""" Test for type for API Field
external_ref field must be int
"""
assert type(self.api_data['external_ref']) is int
def test_api_field_exists_external_system(self):
""" Test for existance of API Field
external_system field must exist
"""
assert 'external_system' in self.api_data
def test_api_field_type_external_system(self):
""" Test for type for API Field
external_system field must be int
"""
assert type(self.api_data['external_system']) is int
def test_api_field_exists_project_type(self):
""" Test for existance of API Field
project_type field must exist
"""
assert 'project_type' in self.api_data
def test_api_field_type_project_type(self):
""" Test for type for API Field
project_type field must be dict
"""
assert type(self.api_data['project_type']) is dict
def test_api_field_exists_project_type_id(self):
""" Test for existance of API Field
project_type.id field must exist
"""
assert 'id' in self.api_data['project_type']
def test_api_field_type_project_type_id(self):
""" Test for type for API Field
project_type.id field must be int
"""
assert type(self.api_data['project_type']['id']) is int
def test_api_field_exists_project_type_display_name(self):
""" Test for existance of API Field
project_type.display_name field must exist
"""
assert 'display_name' in self.api_data['project_type']
def test_api_field_type_project_type_display_name(self):
""" Test for type for API Field
project_type.display_name field must be str
"""
assert type(self.api_data['project_type']['display_name']) is str
def test_api_field_exists_project_type_url(self):
""" Test for existance of API Field
project_type.url field must exist
"""
assert 'url' in self.api_data['project_type']
def test_api_field_type_project_type_url(self):
""" Test for type for API Field
project_type.url field must be Hyperlink
"""
assert type(self.api_data['project_type']['url']) is Hyperlink
def test_api_field_exists_state(self):
""" Test for existance of API Field
state field must exist
"""
assert 'state' in self.api_data
def test_api_field_type_state(self):
""" Test for type for API Field
state field must be dict
"""
assert type(self.api_data['state']) is dict
def test_api_field_exists_state_id(self):
""" Test for existance of API Field
state.id field must exist
"""
assert 'id' in self.api_data['state']
def test_api_field_type_state_id(self):
""" Test for type for API Field
state.id field must be int
"""
assert type(self.api_data['state']['id']) is int
def test_api_field_exists_state_display_name(self):
""" Test for existance of API Field
state.display_name field must exist
"""
assert 'display_name' in self.api_data['state']
def test_api_field_type_state_display_name(self):
""" Test for type for API Field
state.display_name field must be str
"""
assert type(self.api_data['state']['display_name']) is str
def test_api_field_exists_state_url(self):
""" Test for existance of API Field
state.url field must exist
"""
assert 'url' in self.api_data['state']
def test_api_field_type_state_url(self):
""" Test for type for API Field
state.url field must be Hyperlink
"""
assert type(self.api_data['state']['url']) is Hyperlink
def test_api_field_exists_manager_user(self):
""" Test for existance of API Field
manager_user field must exist
"""
assert 'manager_user' in self.api_data
def test_api_field_type_manager_user(self):
""" Test for type for API Field
manager_user field must be dict
"""
assert type(self.api_data['manager_user']) is dict
def test_api_field_exists_manager_user_id(self):
""" Test for existance of API Field
manager_user.id field must exist
"""
assert 'id' in self.api_data['manager_user']
def test_api_field_type_manager_user_id(self):
""" Test for type for API Field
manager_user.id field must be int
"""
assert type(self.api_data['manager_user']['id']) is int
def test_api_field_exists_manager_user_display_name(self):
""" Test for existance of API Field
manager_user.display_name field must exist
"""
assert 'display_name' in self.api_data['manager_user']
def test_api_field_type_manager_user_display_name(self):
""" Test for type for API Field
manager_user.display_name field must be str
"""
assert type(self.api_data['manager_user']['display_name']) is str
def test_api_field_exists_manager_user_url(self):
""" Test for existance of API Field
manager_user.url field must exist
"""
assert 'url' in self.api_data['manager_user']
def test_api_field_type_manager_user_url(self):
""" Test for type for API Field
manager_user.url field must be Hyperlink
"""
assert type(self.api_data['manager_user']['url']) is Hyperlink
def test_api_field_exists_manager_team(self):
""" Test for existance of API Field
manager_team field must exist
"""
assert 'manager_team' in self.api_data
def test_api_field_type_manager_team(self):
""" Test for type for API Field
manager_team field must be dict
"""
assert type(self.api_data['manager_team']) is dict
def test_api_field_exists_manager_team_id(self):
""" Test for existance of API Field
manager_team.id field must exist
"""
assert 'id' in self.api_data['manager_team']
def test_api_field_type_manager_team_id(self):
""" Test for type for API Field
manager_team.id field must be int
"""
assert type(self.api_data['manager_team']['id']) is int
def test_api_field_exists_manager_team_display_name(self):
""" Test for existance of API Field
manager_team.display_name field must exist
"""
assert 'display_name' in self.api_data['manager_team']
def test_api_field_type_manager_team_display_name(self):
""" Test for type for API Field
manager_team.display_name field must be str
"""
assert type(self.api_data['manager_team']['display_name']) is str
def test_api_field_exists_manager_team_url(self):
""" Test for existance of API Field
manager_team.url field must exist
"""
assert 'url' in self.api_data['manager_team']
def test_api_field_type_manager_team_url(self):
""" Test for type for API Field
manager_team.url field must be str
"""
assert type(self.api_data['manager_team']['url']) is str
def test_api_field_exists_team_members(self):
""" Test for existance of API Field
team_members field must exist
"""
assert 'team_members' in self.api_data
def test_api_field_type_team_members(self):
""" Test for type for API Field
team_members field must be dict
"""
assert type(self.api_data['team_members']) is list
def test_api_field_exists_team_members_id(self):
""" Test for existance of API Field
team_members.id field must exist
"""
assert 'id' in self.api_data['team_members'][0]
def test_api_field_type_team_members_id(self):
""" Test for type for API Field
team_members.id field must be int
"""
assert type(self.api_data['team_members'][0]['id']) is int
def test_api_field_exists_team_members_display_name(self):
""" Test for existance of API Field
team_members.display_name field must exist
"""
assert 'display_name' in self.api_data['team_members'][0]
def test_api_field_type_team_members_display_name(self):
""" Test for type for API Field
team_members.display_name field must be str
"""
assert type(self.api_data['team_members'][0]['display_name']) is str
def test_api_field_exists_team_members_url(self):
""" Test for existance of API Field
team_members.url field must exist
"""
assert 'url' in self.api_data['team_members'][0]
def test_api_field_type_team_members_url(self):
""" Test for type for API Field
team_members.url field must be Hyperlink
"""
assert type(self.api_data['team_members'][0]['url']) is Hyperlink

View File

@ -142,7 +142,7 @@ class ClusterModelTestCases(
'team_members': { 'team_members': {
'blank': True, 'blank': True,
'default': models.fields.NOT_PROVIDED, 'default': models.fields.NOT_PROVIDED,
'field_type': models.ForeignKey, 'field_type': models.ManyToManyField,
'null': False, 'null': False,
'unique': False, 'unique': False,
}, },

View File

@ -0,0 +1,188 @@
import pytest
from django.db import models
from rest_framework.exceptions import ValidationError
from api.tests.unit.test_unit_serializer import (
SerializerTestCases
)
from centurion.tests.abstract.mock_view import MockView
from project_management.serializers.project import (
Project,
)
@pytest.mark.model_project
class ProjectSerializerTestCases(
SerializerTestCases
):
@pytest.fixture( scope = 'function' )
def created_model(self, django_db_blocker, model, model_kwargs):
with django_db_blocker.unblock():
kwargs_many_to_many = {}
kwargs = {}
for key, value in model_kwargs.items():
field = model._meta.get_field(key)
if isinstance(field, models.ManyToManyField):
kwargs_many_to_many.update({
key: value
})
else:
kwargs.update({
key: value
})
item = model.objects.create( **kwargs )
for key, value in kwargs_many_to_many.items():
field = getattr(item, key)
for entry in value:
field.add(entry)
yield item
item.delete()
def test_serializer_validation_no_name(self,
kwargs_api_create, model, model_serializer, request_user
):
"""Serializer Validation Check
Ensure that if creating and no name is provided a validation error occurs
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = kwargs_api_create.copy()
del kwargs['name']
with pytest.raises(ValidationError) as err:
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs,
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['name'][0] == 'required'
def test_serializer_validation_external_ref_not_import_user(self,
kwargs_api_create, model, model_serializer, request_user
):
"""Serializer Validation Check
Ensure that if creating by user who is not import user, they can't edit
fields external_ref and external_system.
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = kwargs_api_create.copy()
kwargs['external_ref'] = 1,
kwargs['external_system'] = int(Project.Ticket_ExternalSystem.CUSTOM_1)
mock_view.is_import_user = False
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs,
)
serializer.is_valid(raise_exception = True)
serializer.save()
assert serializer.instance.external_ref is None and serializer.instance.external_system is None
def test_serializer_validation_external_ref_is_import_user(self,
kwargs_api_create, model, model_serializer, request_user
):
"""Serializer Validation Check
Ensure that if creating by user who import user, they can edit
fields external_ref and external_system.
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = kwargs_api_create.copy()
kwargs['external_ref'] = 1
kwargs['external_system'] = int(Project.Ticket_ExternalSystem.CUSTOM_1)
mock_view.is_import_user = True
serializer = model_serializer['import'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs,
)
serializer.is_valid(raise_exception = True)
serializer.save()
assert (
serializer.instance.external_ref == 1 and
serializer.instance.external_system == int(Project.Ticket_ExternalSystem.CUSTOM_1)
)
class ProjectSerializerInheritedCases(
ProjectSerializerTestCases
):
pass
@pytest.mark.module_project_management
class ProjectSerializerPyTest(
ProjectSerializerTestCases
):
pass

View File

@ -1,46 +1,88 @@
import pytest import pytest
from django.test import Client, TestCase
from rest_framework.reverse import reverse
from api.tests.unit.test_unit_common_viewset import ModelViewSetInheritedCases from api.tests.unit.test_unit_common_viewset import ModelViewSetInheritedCases
from project_management.viewsets.project import ViewSet from project_management.viewsets.project import (
Project,
ViewSet,
)
@pytest.mark.skip(reason = 'see #895, tests being refactored')
@pytest.mark.model_project @pytest.mark.model_project
@pytest.mark.module_project_management class ViewsetTestCases(
class ProjectViewsetList(
ModelViewSetInheritedCases, ModelViewSetInheritedCases,
TestCase,
): ):
viewset = ViewSet
route_name = 'v2:_api_project' @pytest.fixture( scope = 'function' )
def viewset(self):
return ViewSet
@classmethod @property
def setUpTestData(self): def parameterized_class_attributes(self):
"""Setup Test return {
'_model_documentation': {
1. make list request 'type': type(None),
""" },
'back_url': {
'type': type(None),
},
'documentation': {
'type': type(None),
'value': None
},
'filterset_fields': {
'value': [
'organization',
'external_system',
'priority',
'project_type',
'state'
]
},
'model': {
'value': Project
},
'model_documentation': {
'type': type(None),
},
'queryset': {
'type': type(None),
},
'serializer_class': {
'type': type(None),
},
'search_fields': {
'value': [
'name',
'description'
]
},
'view_description': {
'value': 'Physical Devices'
},
'view_name': {
'type': type(None),
},
'view_serializer_name': {
'type': type(None),
}
}
super().setUpTestData()
class ProjectViewsetInheritedCases(
ViewsetTestCases,
):
pass
client = Client()
url = reverse( @pytest.mark.module_project_management
self.route_name + '-list', class ProjectViewsetPyTest(
kwargs = self.kwargs ViewsetTestCases,
) ):
client.force_login(self.view_user) pass
self.http_options_response_list = client.options(url)

View File

@ -17,3 +17,9 @@ def model_kwargs(request, kwargs_projectmilestone):
if hasattr(request.cls, 'kwargs_create_item'): if hasattr(request.cls, 'kwargs_create_item'):
del request.cls.kwargs_create_item del request.cls.kwargs_create_item
@pytest.fixture( scope = 'class')
def model_serializer(serializer_projectmilestone):
yield serializer_projectmilestone

View File

@ -1,554 +0,0 @@
import django
import pytest
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse
from django.test import Client, TestCase
from rest_framework.relations import Hyperlink
from access.models.tenant import Tenant as Organization
from access.models.team import Team
from access.models.team_user import TeamUsers
from api.tests.abstract.api_fields import APITenancyObject
from project_management.models.project_milestone import Project, ProjectMilestone
from settings.models.user_settings import UserSettings
User = django.contrib.auth.get_user_model()
@pytest.mark.model_projectmilestone
@pytest.mark.module_project_management
class ProjectMilestoneAPI(
TestCase,
APITenancyObject
):
model = ProjectMilestone
@classmethod
def setUpTestData(self):
"""Setup Test
1. Create an organization for user and item
2. Create an item
"""
self.organization = Organization.objects.create(name='test_org')
project = Project.objects.create(
organization = self.organization,
name = 'a state'
)
view_permissions = Permission.objects.get(
codename = 'view_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
view_team = Team.objects.create(
team_name = 'view_team',
organization = self.organization,
)
view_team.permissions.set([view_permissions])
self.view_user = User.objects.create_user(username="test_user_view", password="password")
user_settings = UserSettings.objects.get(user = self.view_user)
user_settings.default_organization = self.organization
user_settings.save()
teamuser = TeamUsers.objects.create(
team = view_team,
user = self.view_user
)
self.item = self.model.objects.create(
organization = self.organization,
name = 'one',
description = 'notes',
project = project,
start_date = '2024-01-01 00:01:00',
finish_date = '2024-01-01 00:01:01',
)
self.url_view_kwargs = {'project_id': project.id, 'pk': self.item.id}
client = Client()
url = reverse('v2:_api_projectmilestone-detail', kwargs=self.url_view_kwargs)
client.force_login(self.view_user)
response = client.get(url)
self.api_data = response.data
def test_api_field_exists_model_notes(self):
""" Test for existance of API Field
This test is a custom test of a test case with the same name.
this model does not have a model_notes_field
model_notes field must exist
"""
assert 'model_notes' not in self.api_data
def test_api_field_type_model_notes(self):
""" Test for type for API Field
This test is a custom test of a test case with the same name.
this model does not have a model_notes_field
model_notes field must be str
"""
assert True
def test_api_field_exists_description(self):
""" Test for existance of API Field
model_notes field must exist
"""
assert 'description' in self.api_data
def test_api_field_type_description(self):
""" Test for type for API Field
description field must be str
"""
assert type(self.api_data['description']) is str
def test_api_field_exists_start_date(self):
""" Test for existance of API Field
start_date field must exist
"""
assert 'start_date' in self.api_data
def test_api_field_type_start_date(self):
""" Test for type for API Field
start_date field must be str
"""
assert type(self.api_data['start_date']) is str
def test_api_field_exists_finish_date(self):
""" Test for existance of API Field
finish_date field must exist
"""
assert 'finish_date' in self.api_data
def test_api_field_type_finish_date(self):
""" Test for type for API Field
finish_date field must be str
"""
assert type(self.api_data['finish_date']) is str
def test_api_field_exists_project(self):
""" Test for existance of API Field
project field must exist
"""
assert 'project' in self.api_data
def test_api_field_type_project(self):
""" Test for type for API Field
project field must be dict
"""
assert type(self.api_data['project']) is dict
def test_api_field_exists_project_id(self):
""" Test for existance of API Field
project.id field must exist
"""
assert 'id' in self.api_data['project']
def test_api_field_type_project_id(self):
""" Test for type for API Field
project.id field must be int
"""
assert type(self.api_data['project']['id']) is int
def test_api_field_exists_project_display_name(self):
""" Test for existance of API Field
project.display_name field must exist
"""
assert 'display_name' in self.api_data['project']
def test_api_field_type_project_display_name(self):
""" Test for type for API Field
project.display_name field must be str
"""
assert type(self.api_data['project']['display_name']) is str
def test_api_field_exists_project_url(self):
""" Test for existance of API Field
project.url field must exist
"""
assert 'url' in self.api_data['project']
def test_api_field_type_project_url(self):
""" Test for type for API Field
project.url field must be Hyperlink
"""
assert type(self.api_data['project']['url']) is Hyperlink
# def test_api_field_exists_state(self):
# """ Test for existance of API Field
# state field must exist
# """
# assert 'state' in self.api_data
# def test_api_field_type_state(self):
# """ Test for type for API Field
# state field must be dict
# """
# assert type(self.api_data['state']) is dict
# def test_api_field_exists_state_id(self):
# """ Test for existance of API Field
# state.id field must exist
# """
# assert 'id' in self.api_data['state']
# def test_api_field_type_state_id(self):
# """ Test for type for API Field
# state.id field must be int
# """
# assert type(self.api_data['state']['id']) is int
# def test_api_field_exists_state_display_name(self):
# """ Test for existance of API Field
# state.display_name field must exist
# """
# assert 'display_name' in self.api_data['state']
# def test_api_field_type_state_display_name(self):
# """ Test for type for API Field
# state.display_name field must be str
# """
# assert type(self.api_data['state']['display_name']) is str
# def test_api_field_exists_state_url(self):
# """ Test for existance of API Field
# state.url field must exist
# """
# assert 'url' in self.api_data['state']
# def test_api_field_type_state_url(self):
# """ Test for type for API Field
# state.url field must be Hyperlink
# """
# assert type(self.api_data['state']['url']) is Hyperlink
# def test_api_field_exists_manager_user(self):
# """ Test for existance of API Field
# manager_user field must exist
# """
# assert 'manager_user' in self.api_data
# def test_api_field_type_manager_user(self):
# """ Test for type for API Field
# manager_user field must be dict
# """
# assert type(self.api_data['manager_user']) is dict
# def test_api_field_exists_manager_user_id(self):
# """ Test for existance of API Field
# manager_user.id field must exist
# """
# assert 'id' in self.api_data['manager_user']
# def test_api_field_type_manager_user_id(self):
# """ Test for type for API Field
# manager_user.id field must be int
# """
# assert type(self.api_data['manager_user']['id']) is int
# def test_api_field_exists_manager_user_display_name(self):
# """ Test for existance of API Field
# manager_user.display_name field must exist
# """
# assert 'display_name' in self.api_data['manager_user']
# def test_api_field_type_manager_user_display_name(self):
# """ Test for type for API Field
# manager_user.display_name field must be str
# """
# assert type(self.api_data['manager_user']['display_name']) is str
# def test_api_field_exists_manager_user_url(self):
# """ Test for existance of API Field
# manager_user.url field must exist
# """
# assert 'url' in self.api_data['manager_user']
# def test_api_field_type_manager_user_url(self):
# """ Test for type for API Field
# manager_user.url field must be Hyperlink
# """
# assert type(self.api_data['manager_user']['url']) is Hyperlink
# def test_api_field_exists_manager_team(self):
# """ Test for existance of API Field
# manager_team field must exist
# """
# assert 'manager_team' in self.api_data
# def test_api_field_type_manager_team(self):
# """ Test for type for API Field
# manager_team field must be dict
# """
# assert type(self.api_data['manager_team']) is dict
# def test_api_field_exists_manager_team_id(self):
# """ Test for existance of API Field
# manager_team.id field must exist
# """
# assert 'id' in self.api_data['manager_team']
# def test_api_field_type_manager_team_id(self):
# """ Test for type for API Field
# manager_team.id field must be int
# """
# assert type(self.api_data['manager_team']['id']) is int
# def test_api_field_exists_manager_team_display_name(self):
# """ Test for existance of API Field
# manager_team.display_name field must exist
# """
# assert 'display_name' in self.api_data['manager_team']
# def test_api_field_type_manager_team_display_name(self):
# """ Test for type for API Field
# manager_team.display_name field must be str
# """
# assert type(self.api_data['manager_team']['display_name']) is str
# def test_api_field_exists_manager_team_url(self):
# """ Test for existance of API Field
# manager_team.url field must exist
# """
# assert 'url' in self.api_data['manager_team']
# def test_api_field_type_manager_team_url(self):
# """ Test for type for API Field
# manager_team.url field must be str
# """
# assert type(self.api_data['manager_team']['url']) is str
# def test_api_field_exists_team_members(self):
# """ Test for existance of API Field
# team_members field must exist
# """
# assert 'team_members' in self.api_data
# def test_api_field_type_team_members(self):
# """ Test for type for API Field
# team_members field must be dict
# """
# assert type(self.api_data['team_members']) is list
# def test_api_field_exists_team_members_id(self):
# """ Test for existance of API Field
# team_members.id field must exist
# """
# assert 'id' in self.api_data['team_members'][0]
# def test_api_field_type_team_members_id(self):
# """ Test for type for API Field
# team_members.id field must be int
# """
# assert type(self.api_data['team_members'][0]['id']) is int
# def test_api_field_exists_team_members_display_name(self):
# """ Test for existance of API Field
# team_members.display_name field must exist
# """
# assert 'display_name' in self.api_data['team_members'][0]
# def test_api_field_type_team_members_display_name(self):
# """ Test for type for API Field
# team_members.display_name field must be str
# """
# assert type(self.api_data['team_members'][0]['display_name']) is str
# def test_api_field_exists_team_members_url(self):
# """ Test for existance of API Field
# team_members.url field must exist
# """
# assert 'url' in self.api_data['team_members'][0]
# def test_api_field_type_team_members_url(self):
# """ Test for type for API Field
# team_members.url field must be Hyperlink
# """
# assert type(self.api_data['team_members'][0]['url']) is Hyperlink

View File

@ -0,0 +1,171 @@
import pytest
from django.db import models
from rest_framework.exceptions import ValidationError
from api.tests.unit.test_unit_serializer import (
SerializerTestCases
)
from centurion.tests.abstract.mock_view import MockView
# from project_management.serializers.project import (
# ProjectMilestone,
# )
@pytest.mark.model_projectmilestone
class ProjectMilestoneSerializerTestCases(
SerializerTestCases
):
# @pytest.fixture( scope = 'function' )
# def created_model(self, django_db_blocker, model, model_kwargs):
# with django_db_blocker.unblock():
# kwargs_many_to_many = {}
# kwargs = {}
# for key, value in model_kwargs.items():
# field = model._meta.get_field(key)
# if isinstance(field, models.ManyToManyField):
# kwargs_many_to_many.update({
# key: value
# })
# else:
# kwargs.update({
# key: value
# })
# item = model.objects.create( **kwargs )
# for key, value in kwargs_many_to_many.items():
# field = getattr(item, key)
# for entry in value:
# field.add(entry)
# yield item
# item.delete()
def test_serializer_validation_no_name(self,
kwargs_api_create, model, model_serializer, request_user
):
"""Serializer Validation Check
Ensure that if creating and no name is provided a validation error occurs
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = kwargs_api_create.copy()
del kwargs['name']
with pytest.raises(ValidationError) as err:
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs,
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['name'][0] == 'required'
def test_serializer_is_valid(self, kwargs_api_create, model, model_serializer, request_user):
""" Serializer Check
Confirm that using valid data the object validates without exceptions.
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
mock_view.kwargs = { 'project_id': kwargs_api_create['project'] }
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs_api_create
)
assert serializer.is_valid(raise_exception = True)
@pytest.mark.regression
def test_serializer_create_calls_model_full_clean(self,
kwargs_api_create, mocker, model, model_serializer, request_user
):
""" Serializer Check
Confirm that using valid data the object validates without exceptions.
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
mock_view.kwargs = { 'project_id': kwargs_api_create['project'] }
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs_api_create
)
serializer.is_valid(raise_exception = True)
full_clean = mocker.spy(model, 'full_clean')
serializer.save()
full_clean.assert_called_once()
class ProjectMilestoneSerializerInheritedCases(
ProjectMilestoneSerializerTestCases
):
pass
@pytest.mark.module_project_management
class ProjectMilestoneSerializerPyTest(
ProjectMilestoneSerializerTestCases
):
pass

View File

@ -1,54 +1,130 @@
import pytest import pytest
from django.test import Client, TestCase
from rest_framework.reverse import reverse
from api.tests.unit.test_unit_common_viewset import ModelViewSetInheritedCases from api.tests.unit.test_unit_common_viewset import ModelViewSetInheritedCases
from project_management.models.projects import Project from project_management.viewsets.project_milestone import (
from project_management.viewsets.project_milestone import ViewSet ProjectMilestone,
ViewSet,
)
@pytest.mark.skip(reason = 'see #895, tests being refactored')
@pytest.mark.model_projectmilestone @pytest.mark.model_projectmilestone
@pytest.mark.module_project_management class ViewsetTestCases(
class ProjectMilestoneViewsetList(
ModelViewSetInheritedCases, ModelViewSetInheritedCases,
TestCase,
): ):
viewset = ViewSet
route_name = 'v2:_api_projectmilestone' @pytest.fixture( scope = 'function' )
def viewset(self):
return ViewSet
@classmethod @property
def setUpTestData(self): def parameterized_class_attributes(self):
"""Setup Test return {
'_model_documentation': {
1. make list request 'type': type(None),
""" },
'back_url': {
'type': type(None),
super().setUpTestData() },
'documentation': {
self.kwargs = { 'type': type(None),
'project_id': Project.objects.create( 'value': None
organization = self.organization, },
name = 'proj' 'filterset_fields': {
).id 'value': []
},
'model': {
'value': ProjectMilestone
},
'model_documentation': {
'type': type(None),
},
'queryset': {
'type': type(None),
},
'serializer_class': {
'type': type(None),
},
'search_fields': {
'value': [
'name',
'description'
]
},
'view_description': {
'value': 'Physical Devices'
},
'view_name': {
'type': type(None),
},
'view_serializer_name': {
'type': type(None),
}
} }
client = Client() def test_view_func_get_queryset_cache_result(self, viewset_mock_request,
model_kwargs
url = reverse( ):
self.route_name + '-list', """Viewset Test
kwargs = self.kwargs
)
client.force_login(self.view_user) Ensure that the `get_queryset` function caches the result under
attribute `<viewset>.queryset`
"""
self.http_options_response_list = client.options(url) view_set = viewset_mock_request
view_set.kwargs = { 'project_id': model_kwargs['project'].id }
assert view_set.queryset is None # Must be empty before init
q = view_set.get_queryset()
assert view_set.queryset is not None # Must not be empty after init
assert q == view_set.queryset
def test_view_func_get_queryset_cache_result_used(self, mocker, viewset, viewset_mock_request,
model_kwargs
):
"""Viewset Test
Ensure that the `get_queryset` function caches the result under
attribute `<viewset>.queryset`
"""
qs = mocker.spy(viewset_mock_request.model, 'objects')
view_set = viewset_mock_request
view_set.kwargs = { 'project_id': model_kwargs['project'].id }
view_set.get_queryset() # Initial QuerySet fetch/filter and cache
assert len(qs.method_calls) == 1 # one call to .all()
assert len(qs.mock_calls) == 3 # calls = .all(), all().filter()
view_set.get_queryset() # Use Cached results, dont re-fetch QuerySet
assert len(qs.method_calls) == 1
assert len(qs.mock_calls) == 3
class ProjectMilestoneViewsetInheritedCases(
ViewsetTestCases,
):
pass
@pytest.mark.module_project_management
class ProjectMilestoneViewsetPyTest(
ViewsetTestCases,
):
pass

View File

@ -17,3 +17,9 @@ def model_kwargs(request, kwargs_projectstate):
if hasattr(request.cls, 'kwargs_create_item'): if hasattr(request.cls, 'kwargs_create_item'):
del request.cls.kwargs_create_item del request.cls.kwargs_create_item
@pytest.fixture( scope = 'class')
def model_serializer(serializer_projectstate):
yield serializer_projectstate

View File

@ -1,217 +0,0 @@
import django
import pytest
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse
from django.test import Client, TestCase
from access.models.tenant import Tenant as Organization
from access.models.team import Team
from access.models.team_user import TeamUsers
from api.tests.abstract.api_fields import APITenancyObject
from assistance.models.knowledge_base import KnowledgeBase, KnowledgeBaseCategory
from project_management.models.projects import ProjectState
from settings.models.user_settings import UserSettings
User = django.contrib.auth.get_user_model()
@pytest.mark.model_projectstate
@pytest.mark.module_project_management
class ProjectStateAPI(
TestCase,
APITenancyObject
):
model = ProjectState
@classmethod
def setUpTestData(self):
"""Setup Test
1. Create an organization for user and item
2. Create an item
"""
self.organization = Organization.objects.create(name='test_org')
self.view_user = User.objects.create_user(username="test_user_view", password="password")
kb = KnowledgeBase.objects.create(
organization = self.organization,
title = 'kb article',
category = KnowledgeBaseCategory.objects.create(
organization = self.organization,
name = 'kb_cat'
),
responsible_user = self.view_user,
target_user = self.view_user,
)
self.item = ProjectState.objects.create(
organization = self.organization,
name = 'a state',
model_notes = 'note',
runbook = kb,
)
view_permissions = Permission.objects.get(
codename = 'view_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
view_team = Team.objects.create(
team_name = 'view_team',
organization = self.organization,
)
view_team.permissions.set([view_permissions])
user_settings = UserSettings.objects.get(user = self.view_user)
user_settings.default_organization = self.organization
user_settings.save()
teamuser = TeamUsers.objects.create(
team = view_team,
user = self.view_user
)
# self.item = self.model.objects.create(
# organization = self.organization,
# name = 'one',
# state = project_state,
# runbook = runbook,
# description = 'a note',
# manager_user = self.view_user,
# manager_team = view_team,
# planned_start_date = '2024-01-01 00:01:00',
# planned_finish_date = '2024-01-01 00:01:01',
# real_start_date = '2024-01-02 00:01:00',
# real_finish_date = '2024-01-02 00:01:01',
# code = 'acode',
# external_ref = 1,
# external_system = Project.Ticket_ExternalSystem.CUSTOM_1
# )
# self.item.team_members.set([ self.view_user ])
self.url_view_kwargs = {'pk': self.item.id}
client = Client()
url = reverse('v2:_api_projectstate-detail', kwargs=self.url_view_kwargs)
client.force_login(self.view_user)
response = client.get(url)
self.api_data = response.data
def test_api_field_exists_is_completed(self):
""" Test for existance of API Field
is_completed field must exist
"""
assert 'is_completed' in self.api_data
def test_api_field_type_is_completed(self):
""" Test for type for API Field
is_completed field must be bool
"""
assert type(self.api_data['is_completed']) is bool
def test_api_field_exists_runbook(self):
""" Test for existance of API Field
runbook field must exist
"""
assert 'runbook' in self.api_data
def test_api_field_type_runbook(self):
""" Test for type for API Field
runbook field must be dict
"""
assert type(self.api_data['runbook']) is dict
def test_api_field_exists_runbook_id(self):
""" Test for existance of API Field
runbook.id field must exist
"""
assert 'id' in self.api_data['runbook']
def test_api_field_type_runbook_id(self):
""" Test for type for API Field
runbook.id field must be int
"""
assert type(self.api_data['runbook']['id']) is int
def test_api_field_exists_runbook_display_name(self):
""" Test for existance of API Field
runbook.display_name field must exist
"""
assert 'display_name' in self.api_data['runbook']
def test_api_field_type_runbook_display_name(self):
""" Test for type for API Field
runbook.display_name field must be str
"""
assert type(self.api_data['runbook']['display_name']) is str
def test_api_field_exists_runbook_url(self):
""" Test for existance of API Field
runbook.url field must exist
"""
assert 'url' in self.api_data['runbook']
def test_api_field_type_runbook_url(self):
""" Test for type for API Field
runbook.url field must be str
"""
assert type(self.api_data['runbook']['url']) is str

View File

@ -0,0 +1,68 @@
import pytest
from django.db import models
from rest_framework.exceptions import ValidationError
from api.tests.unit.test_unit_serializer import (
SerializerTestCases
)
from centurion.tests.abstract.mock_view import MockView
# from project_management.serializers.project import (
# ProjectState,
# )
@pytest.mark.model_projectstate
class ProjectStateSerializerTestCases(
SerializerTestCases
):
def test_serializer_validation_no_name(self,
kwargs_api_create, model, model_serializer, request_user
):
"""Serializer Validation Check
Ensure that if creating and no name is provided a validation error occurs
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = kwargs_api_create.copy()
del kwargs['name']
with pytest.raises(ValidationError) as err:
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs,
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['name'][0] == 'required'
class ProjectStateSerializerInheritedCases(
ProjectStateSerializerTestCases
):
pass
@pytest.mark.module_project_management
class ProjectStateSerializerPyTest(
ProjectStateSerializerTestCases
):
pass

View File

@ -1,45 +1,83 @@
import pytest import pytest
from django.test import Client, TestCase
from rest_framework.reverse import reverse
from api.tests.unit.test_unit_common_viewset import ModelViewSetInheritedCases from api.tests.unit.test_unit_common_viewset import ModelViewSetInheritedCases
from project_management.viewsets.project_state import ViewSet from project_management.viewsets.project_state import (
ProjectState,
ViewSet,
)
@pytest.mark.skip(reason = 'see #895, tests being refactored')
@pytest.mark.model_projectstate @pytest.mark.model_projectstate
@pytest.mark.module_project_management class ViewsetTestCases(
class ProjectStateViewsetList(
ModelViewSetInheritedCases, ModelViewSetInheritedCases,
TestCase,
): ):
viewset = ViewSet
route_name = 'v2:_api_projectstate' @pytest.fixture( scope = 'function' )
def viewset(self):
return ViewSet
@classmethod @property
def setUpTestData(self): def parameterized_class_attributes(self):
"""Setup Test return {
'_model_documentation': {
1. make list request 'type': type(None),
""" },
'back_url': {
super().setUpTestData() 'type': type(None),
},
'documentation': {
'type': type(None),
'value': None
},
'filterset_fields': {
'value': [
'organization'
]
},
'model': {
'value': ProjectState
},
'model_documentation': {
'type': type(None),
},
'queryset': {
'type': type(None),
},
'serializer_class': {
'type': type(None),
},
'search_fields': {
'value': [
'name'
]
},
'view_description': {
'value': 'Physical Devices'
},
'view_name': {
'type': type(None),
},
'view_serializer_name': {
'type': type(None),
}
}
client = Client()
url = reverse(
self.route_name + '-list',
kwargs = self.kwargs
)
client.force_login(self.view_user) class ProjectStateViewsetInheritedCases(
ViewsetTestCases,
):
pass
self.http_options_response_list = client.options(url)
@pytest.mark.module_project_management
class ProjectStateViewsetPyTest(
ViewsetTestCases,
):
pass

View File

@ -17,3 +17,9 @@ def model_kwargs(request, kwargs_projecttype):
if hasattr(request.cls, 'kwargs_create_item'): if hasattr(request.cls, 'kwargs_create_item'):
del request.cls.kwargs_create_item del request.cls.kwargs_create_item
@pytest.fixture( scope = 'class')
def model_serializer(serializer_projecttype):
yield serializer_projecttype

View File

@ -1,179 +0,0 @@
import django
import pytest
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse
from django.test import Client, TestCase
from access.models.tenant import Tenant as Organization
from access.models.team import Team
from access.models.team_user import TeamUsers
from api.tests.abstract.api_fields import APITenancyObject
from assistance.models.knowledge_base import KnowledgeBase, KnowledgeBaseCategory
from project_management.models.project_types import ProjectType
from settings.models.user_settings import UserSettings
User = django.contrib.auth.get_user_model()
@pytest.mark.model_projecttype
@pytest.mark.module_project_management
class ProjectTypeAPI(
TestCase,
APITenancyObject
):
model = ProjectType
@classmethod
def setUpTestData(self):
"""Setup Test
1. Create an organization for user and item
2. Create an item
"""
self.organization = Organization.objects.create(name='test_org')
self.view_user = User.objects.create_user(username="test_user_view", password="password")
kb = KnowledgeBase.objects.create(
organization = self.organization,
title = 'kb article',
category = KnowledgeBaseCategory.objects.create(
organization = self.organization,
name = 'kb_cat'
),
responsible_user = self.view_user,
target_user = self.view_user,
)
self.item = self.model.objects.create(
organization = self.organization,
name = 'a state',
model_notes = 'note',
runbook = kb,
)
view_permissions = Permission.objects.get(
codename = 'view_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
view_team = Team.objects.create(
team_name = 'view_team',
organization = self.organization,
)
view_team.permissions.set([view_permissions])
user_settings = UserSettings.objects.get(user = self.view_user)
user_settings.default_organization = self.organization
user_settings.save()
teamuser = TeamUsers.objects.create(
team = view_team,
user = self.view_user
)
self.url_view_kwargs = {'pk': self.item.id}
client = Client()
url = reverse('v2:_api_projecttype-detail', kwargs=self.url_view_kwargs)
client.force_login(self.view_user)
response = client.get(url)
self.api_data = response.data
def test_api_field_exists_runbook(self):
""" Test for existance of API Field
runbook field must exist
"""
assert 'runbook' in self.api_data
def test_api_field_type_runbook(self):
""" Test for type for API Field
runbook field must be dict
"""
assert type(self.api_data['runbook']) is dict
def test_api_field_exists_runbook_id(self):
""" Test for existance of API Field
runbook.id field must exist
"""
assert 'id' in self.api_data['runbook']
def test_api_field_type_runbook_id(self):
""" Test for type for API Field
runbook.id field must be int
"""
assert type(self.api_data['runbook']['id']) is int
def test_api_field_exists_runbook_display_name(self):
""" Test for existance of API Field
runbook.display_name field must exist
"""
assert 'display_name' in self.api_data['runbook']
def test_api_field_type_runbook_display_name(self):
""" Test for type for API Field
runbook.display_name field must be str
"""
assert type(self.api_data['runbook']['display_name']) is str
def test_api_field_exists_runbook_url(self):
""" Test for existance of API Field
runbook.url field must exist
"""
assert 'url' in self.api_data['runbook']
def test_api_field_type_runbook_url(self):
""" Test for type for API Field
runbook.url field must be str
"""
assert type(self.api_data['runbook']['url']) is str

View File

@ -0,0 +1,65 @@
import pytest
from django.db import models
from rest_framework.exceptions import ValidationError
from api.tests.unit.test_unit_serializer import (
SerializerTestCases
)
from centurion.tests.abstract.mock_view import MockView
@pytest.mark.model_projecttype
class ProjectTypeSerializerTestCases(
SerializerTestCases
):
def test_serializer_validation_no_name(self,
kwargs_api_create, model, model_serializer, request_user
):
"""Serializer Validation Check
Ensure that if creating and no name is provided a validation error occurs
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = kwargs_api_create.copy()
del kwargs['name']
with pytest.raises(ValidationError) as err:
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs,
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['name'][0] == 'required'
class ProjectTypeSerializerInheritedCases(
ProjectTypeSerializerTestCases
):
pass
@pytest.mark.module_project_management
class ProjectTypeSerializerPyTest(
ProjectTypeSerializerTestCases
):
pass

View File

@ -1,46 +1,83 @@
import pytest import pytest
from django.test import Client, TestCase
from rest_framework.reverse import reverse
from api.tests.unit.test_unit_common_viewset import ModelViewSetInheritedCases from api.tests.unit.test_unit_common_viewset import ModelViewSetInheritedCases
from project_management.viewsets.project_state import ViewSet from project_management.viewsets.project_type import (
ProjectType,
ViewSet,
)
@pytest.mark.skip(reason = 'see #895, tests being refactored')
@pytest.mark.model_projecttype @pytest.mark.model_projecttype
@pytest.mark.module_project_management class ViewsetTestCases(
class ProjectTypeViewsetList(
ModelViewSetInheritedCases, ModelViewSetInheritedCases,
TestCase,
): ):
viewset = ViewSet
route_name = 'v2:_api_projecttype' @pytest.fixture( scope = 'function' )
def viewset(self):
return ViewSet
@classmethod @property
def setUpTestData(self): def parameterized_class_attributes(self):
"""Setup Test return {
'_model_documentation': {
1. make list request 'type': type(None),
""" },
'back_url': {
'type': type(None),
},
'documentation': {
'type': type(None),
'value': None
},
'filterset_fields': {
'value': [
'organization'
]
},
'model': {
'value': ProjectType
},
'model_documentation': {
'type': type(None),
},
'queryset': {
'type': type(None),
},
'serializer_class': {
'type': type(None),
},
'search_fields': {
'value': [
'name'
]
},
'view_description': {
'value': 'Physical Devices'
},
'view_name': {
'type': type(None),
},
'view_serializer_name': {
'type': type(None),
}
}
super().setUpTestData()
class ProjectTypeViewsetInheritedCases(
ViewsetTestCases,
):
pass
client = Client()
url = reverse( @pytest.mark.module_project_management
self.route_name + '-list', class ProjectTypeViewsetPyTest(
kwargs = self.kwargs ViewsetTestCases,
) ):
client.force_login(self.view_user) pass
self.http_options_response_list = client.options(url)

View File

@ -36,14 +36,14 @@ class AppSettingsModelTestCases(
'model_notes': { 'model_notes': {
'blank': models.fields.NOT_PROVIDED, 'blank': models.fields.NOT_PROVIDED,
'default': models.fields.NOT_PROVIDED, 'default': models.fields.NOT_PROVIDED,
'field_type': models.CharField, 'field_type': models.fields.NOT_PROVIDED,
'null': models.fields.NOT_PROVIDED, 'null': models.fields.NOT_PROVIDED,
'unique': models.fields.NOT_PROVIDED, 'unique': models.fields.NOT_PROVIDED,
}, },
'organization': { 'organization': {
'blank': models.fields.NOT_PROVIDED, 'blank': models.fields.NOT_PROVIDED,
'default': models.fields.NOT_PROVIDED, 'default': models.fields.NOT_PROVIDED,
'field_type': models.CharField, 'field_type': models.fields.NOT_PROVIDED,
'null': models.fields.NOT_PROVIDED, 'null': models.fields.NOT_PROVIDED,
'unique': models.fields.NOT_PROVIDED, 'unique': models.fields.NOT_PROVIDED,
}, },

View File

@ -43,14 +43,14 @@ class UserSettingsModelTestCases(
'model_notes': { 'model_notes': {
'blank': models.fields.NOT_PROVIDED, 'blank': models.fields.NOT_PROVIDED,
'default': models.fields.NOT_PROVIDED, 'default': models.fields.NOT_PROVIDED,
'field_type': models.CharField, 'field_type': models.fields.NOT_PROVIDED,
'null': models.fields.NOT_PROVIDED, 'null': models.fields.NOT_PROVIDED,
'unique': models.fields.NOT_PROVIDED, 'unique': models.fields.NOT_PROVIDED,
}, },
'organization': { 'organization': {
'blank': models.fields.NOT_PROVIDED, 'blank': models.fields.NOT_PROVIDED,
'default': models.fields.NOT_PROVIDED, 'default': models.fields.NOT_PROVIDED,
'field_type': models.CharField, 'field_type': models.fields.NOT_PROVIDED,
'null': models.fields.NOT_PROVIDED, 'null': models.fields.NOT_PROVIDED,
'unique': models.fields.NOT_PROVIDED, 'unique': models.fields.NOT_PROVIDED,
}, },

View File

@ -236,21 +236,25 @@ from .model_port import (
from .model_project import ( from .model_project import (
kwargs_project, kwargs_project,
model_project, model_project,
serializer_project,
) )
from .model_projectmilestone import ( from .model_projectmilestone import (
kwargs_projectmilestone, kwargs_projectmilestone,
model_projectmilestone, model_projectmilestone,
serializer_projectmilestone,
) )
from .model_projectstate import ( from .model_projectstate import (
kwargs_projectstate, kwargs_projectstate,
model_projectstate, model_projectstate,
serializer_projectstate,
) )
from .model_projecttype import ( from .model_projecttype import (
kwargs_projecttype, kwargs_projecttype,
model_projecttype, model_projecttype,
serializer_projecttype,
) )
from .model_requestticket import ( from .model_requestticket import (

View File

@ -1,6 +1,8 @@
import datetime import datetime
import pytest import pytest
from django.db import models
from assistance.models.knowledge_base import KnowledgeBase from assistance.models.knowledge_base import KnowledgeBase
from assistance.serializers.knowledge_base import ( from assistance.serializers.knowledge_base import (
KnowledgeBaseBaseSerializer, KnowledgeBaseBaseSerializer,
@ -66,10 +68,14 @@ def kwargs_knowledgebase(django_db_blocker,
try: try:
user.delete() user.delete()
except: except models.deletion.ProtectedError:
pass
try:
category.delete()
except models.deletion.ProtectedError:
pass pass
category.delete()
@pytest.fixture( scope = 'class') @pytest.fixture( scope = 'class')

View File

@ -1,7 +1,16 @@
import datetime import datetime
import pytest import pytest
import random
from django.db import models
from project_management.models.projects import Project from project_management.models.projects import Project
from project_management.serializers.project import (
ProjectBaseSerializer,
ProjectImportSerializer,
ProjectModelSerializer,
ProjectViewSerializer,
)
@ -12,19 +21,81 @@ def model_project():
@pytest.fixture( scope = 'class') @pytest.fixture( scope = 'class')
def kwargs_project(kwargs_centurionmodel): def kwargs_project(kwargs_centurionmodel, django_db_blocker,
model_projectstate, kwargs_projectstate,
model_projecttype, kwargs_projecttype,
model_user, kwargs_user,
):
random_str = str(datetime.datetime.now(tz=datetime.timezone.utc)) random_str = str(datetime.datetime.now(tz=datetime.timezone.utc))
random_str = str(random_str).replace( random_str = str(random_str).replace(
' ', '').replace(':', '').replace('+', '').replace('.', '') ' ', '').replace(':', '').replace('+', '').replace('.', '')
with django_db_blocker.unblock():
state = model_projectstate.objects.create( **kwargs_projectstate )
pr_type = model_projecttype.objects.create( **kwargs_projecttype )
kwargs = kwargs_user.copy()
kwargs['username'] = 'tm_proj' + str( random.randint(333, 666) )
manager = model_user.objects.create( **kwargs )
kwargs = kwargs_user.copy()
kwargs['username'] = 'tm_proj' + str( random.randint(777, 999) )
team_member = model_user.objects.create( **kwargs )
kwargs = kwargs_centurionmodel.copy() kwargs = kwargs_centurionmodel.copy()
del kwargs['model_notes'] del kwargs['model_notes']
kwargs = { kwargs = {
**kwargs, **kwargs,
'code': 'aCODE',
'name': 'project_' + random_str, 'name': 'project_' + random_str,
'description': 'a description',
'priority': Project.Priority.LOW, 'priority': Project.Priority.LOW,
'state': state,
'project_type': pr_type,
'planned_start_date': '2025-08-04T00:00:01Z',
'planned_finish_date': '2025-08-04T00:00:02Z',
'real_start_date': '2025-08-04T00:00:03Z',
'real_finish_date': '2025-08-04T00:00:04Z',
'manager_user': manager,
'team_members': [ team_member ],
} }
yield kwargs.copy() yield kwargs.copy()
with django_db_blocker.unblock():
try:
state.delete()
except models.deletion.ProtectedError:
pass
try:
pr_type.delete()
except models.deletion.ProtectedError:
pass
try:
manager.delete()
except models.deletion.ProtectedError:
pass
try:
team_member.delete()
except models.deletion.ProtectedError:
pass
@pytest.fixture( scope = 'class')
def serializer_project():
yield {
'base': ProjectBaseSerializer,
'import': ProjectImportSerializer,
'model': ProjectModelSerializer,
'view': ProjectViewSerializer
}

View File

@ -1,7 +1,14 @@
import datetime import datetime
import pytest import pytest
from django.db import models
from project_management.models.project_milestone import ProjectMilestone from project_management.models.project_milestone import ProjectMilestone
from project_management.serializers.project_milestone import (
ProjectMilestoneBaseSerializer,
ProjectMilestoneModelSerializer,
ProjectMilestoneViewSerializer,
)
@ -22,15 +29,39 @@ def kwargs_projectmilestone(django_db_blocker,
with django_db_blocker.unblock(): with django_db_blocker.unblock():
kwargs = kwargs_project.copy() # kwargs = kwargs_project.copy()
kwargs_many_to_many = {}
kwargs = {}
for key, value in kwargs_project.items():
field = model_project._meta.get_field(key)
if isinstance(field, models.ManyToManyField):
kwargs_many_to_many.update({
key: value
})
else:
kwargs.update({
key: value
})
kwargs.update({ kwargs.update({
'name': 'pm' + random_str 'name': 'pm' + random_str
}) })
del kwargs['code']
project = model_project.objects.create( project = model_project.objects.create(
**kwargs **kwargs
) )
kwargs = kwargs_centurionmodel.copy() kwargs = kwargs_centurionmodel.copy()
del kwargs['model_notes'] del kwargs['model_notes']
@ -38,6 +69,8 @@ def kwargs_projectmilestone(django_db_blocker,
**kwargs, **kwargs,
'name': 'pm_' + random_str, 'name': 'pm_' + random_str,
'project': project, 'project': project,
'start_date': '2025-08-04T00:00:01Z',
'finish_date': '2025-08-04T00:00:02Z',
} }
yield kwargs.copy() yield kwargs.copy()
@ -45,3 +78,13 @@ def kwargs_projectmilestone(django_db_blocker,
# with django_db_blocker.unblock(): # with django_db_blocker.unblock():
# project.delete() # milestone is cascade delete # project.delete() # milestone is cascade delete
@pytest.fixture( scope = 'class')
def serializer_projectmilestone():
yield {
'base': ProjectMilestoneBaseSerializer,
'model': ProjectMilestoneModelSerializer,
'view': ProjectMilestoneViewSerializer
}

View File

@ -1,8 +1,14 @@
import datetime import datetime
import pytest import pytest
from project_management.models.project_states import ProjectState from django.db import models
from project_management.models.project_states import ProjectState
from project_management.serializers.project_states import (
ProjectStateBaseSerializer,
ProjectStateModelSerializer,
ProjectStateViewSerializer,
)
@pytest.fixture( scope = 'class') @pytest.fixture( scope = 'class')
@ -12,18 +18,47 @@ def model_projectstate():
@pytest.fixture( scope = 'class') @pytest.fixture( scope = 'class')
def kwargs_projectstate(kwargs_centurionmodel): def kwargs_projectstate(kwargs_centurionmodel, django_db_blocker,
model_knowledgebase, kwargs_knowledgebase,
):
random_str = str(datetime.datetime.now(tz=datetime.timezone.utc)) random_str = str(datetime.datetime.now(tz=datetime.timezone.utc))
random_str = str(random_str).replace( random_str = str(random_str).replace(
' ', '').replace(':', '').replace('+', '').replace('.', '') ' ', '').replace(':', '').replace('+', '').replace('.', '')
with django_db_blocker.unblock():
kwargs = kwargs_knowledgebase.copy()
team = kwargs['target_team']
del kwargs['target_team']
runbook = model_knowledgebase.objects.create( **kwargs )
runbook.target_team.add( team[0] )
kwargs = kwargs_centurionmodel.copy() kwargs = kwargs_centurionmodel.copy()
del kwargs['model_notes']
kwargs = { kwargs = {
**kwargs, **kwargs,
'name': 'projectstate_' + random_str, 'name': 'projectstate_' + random_str,
'runbook': runbook,
} }
yield kwargs.copy() yield kwargs.copy()
with django_db_blocker.unblock():
try:
runbook.delete()
except models.deletion.ProtectedError:
pass
@pytest.fixture( scope = 'class')
def serializer_projectstate():
yield {
'base': ProjectStateBaseSerializer,
'model': ProjectStateModelSerializer,
'view': ProjectStateViewSerializer
}

View File

@ -1,7 +1,14 @@
import datetime import datetime
import pytest import pytest
from django.db import models
from project_management.models.project_types import ProjectType from project_management.models.project_types import ProjectType
from project_management.serializers.project_type import (
ProjectTypeBaseSerializer,
ProjectTypeModelSerializer,
ProjectTypeViewSerializer,
)
@ -12,15 +19,45 @@ def model_projecttype():
@pytest.fixture( scope = 'class') @pytest.fixture( scope = 'class')
def kwargs_projecttype(kwargs_centurionmodel): def kwargs_projecttype(kwargs_centurionmodel, django_db_blocker,
model_knowledgebase, kwargs_knowledgebase,
):
random_str = str(datetime.datetime.now(tz=datetime.timezone.utc)) random_str = str(datetime.datetime.now(tz=datetime.timezone.utc))
random_str = str(random_str).replace( random_str = str(random_str).replace(
' ', '').replace(':', '').replace('+', '').replace('.', '') ' ', '').replace(':', '').replace('+', '').replace('.', '')
with django_db_blocker.unblock():
kwargs = kwargs_knowledgebase.copy()
team = kwargs['target_team']
del kwargs['target_team']
runbook = model_knowledgebase.objects.create( **kwargs )
runbook.target_team.add( team[0] )
kwargs = { kwargs = {
**kwargs_centurionmodel.copy(), **kwargs_centurionmodel.copy(),
'name': 'projecttype_' + random_str, 'name': 'projecttype_' + random_str,
'runbook': runbook,
} }
yield kwargs.copy() yield kwargs.copy()
with django_db_blocker.unblock():
try:
runbook.delete()
except models.deletion.ProtectedError:
pass
@pytest.fixture( scope = 'class')
def serializer_projecttype():
yield {
'base': ProjectTypeBaseSerializer,
'model': ProjectTypeModelSerializer,
'view': ProjectTypeViewSerializer
}