diff --git a/app/conftest.py b/app/conftest.py index d11dfcc9..1f075290 100644 --- a/app/conftest.py +++ b/app/conftest.py @@ -262,6 +262,15 @@ def pytest_generate_tests(metafunc): 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( argnames = [ *fixture_parameters diff --git a/app/core/tests/unit/ticket_base/test_unit_ticket_base_model.py b/app/core/tests/unit/ticket_base/test_unit_ticket_base_model.py index d6e0aa7f..f2d1d9fc 100644 --- a/app/core/tests/unit/ticket_base/test_unit_ticket_base_model.py +++ b/app/core/tests/unit/ticket_base/test_unit_ticket_base_model.py @@ -262,7 +262,13 @@ class TicketBaseModelTestCases( 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 @@ -271,7 +277,12 @@ class TicketBaseModelTestCases( kwargs = kwargs_project 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.team_members.add( team_members[0] ) kwargs = kwargs_projectmilestone kwargs['name'] = 'two' diff --git a/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_model.py b/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_model.py index fc2330cf..3f72bcca 100644 --- a/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_model.py +++ b/app/core/tests/unit/ticket_comment_base/test_unit_ticket_comment_base_model.py @@ -148,7 +148,7 @@ class TicketCommentBaseModelTestCases( "is_closed": { 'blank': False, 'default': False, - 'field_type': models.fields.IntegerField, + 'field_type': models.fields.BooleanField, 'null': False, 'unique': False, }, diff --git a/app/devops/tests/unit/git_group/test_unit_git_group_model.py b/app/devops/tests/unit/git_group/test_unit_git_group_model.py index 7ea53421..c7833143 100644 --- a/app/devops/tests/unit/git_group/test_unit_git_group_model.py +++ b/app/devops/tests/unit/git_group/test_unit_git_group_model.py @@ -54,7 +54,7 @@ class GitGroupModelTestCases( 'name': { 'blank': False, 'default': models.fields.NOT_PROVIDED, - 'field_type': models.IntegerField, + 'field_type': models.CharField, 'length': 80, 'null': False, 'unique': False, @@ -62,7 +62,7 @@ class GitGroupModelTestCases( 'path': { 'blank': False, 'default': models.fields.NOT_PROVIDED, - 'field_type': models.IntegerField, + 'field_type': models.CharField, 'length': 80, 'null': False, 'unique': False, @@ -70,7 +70,7 @@ class GitGroupModelTestCases( 'description': { 'blank': True, 'default': models.fields.NOT_PROVIDED, - 'field_type': models.IntegerField, + 'field_type': models.TextField, 'max_length': 80, 'null': True, 'unique': False, diff --git a/app/devops/tests/unit/gitlab_repository/test_unit_gitlab_repository_model.py b/app/devops/tests/unit/gitlab_repository/test_unit_gitlab_repository_model.py index fa071543..f11a83da 100644 --- a/app/devops/tests/unit/gitlab_repository/test_unit_gitlab_repository_model.py +++ b/app/devops/tests/unit/gitlab_repository/test_unit_gitlab_repository_model.py @@ -25,7 +25,7 @@ class GitLabRepositoryBaseModelTestCases( 'visibility': { 'blank': False, 'default': models.NOT_PROVIDED, - 'field_type': models.BooleanField, + 'field_type': models.IntegerField, 'null': False, 'unique': False, } diff --git a/app/devops/tests/unit/software_enable_feature_flag/test_unit_software_enable_feature_flag_model.py b/app/devops/tests/unit/software_enable_feature_flag/test_unit_software_enable_feature_flag_model.py index 5c50f4c1..778ae19e 100644 --- a/app/devops/tests/unit/software_enable_feature_flag/test_unit_software_enable_feature_flag_model.py +++ b/app/devops/tests/unit/software_enable_feature_flag/test_unit_software_enable_feature_flag_model.py @@ -53,7 +53,7 @@ class SoftwareEnableFeatureFlagModelTestCases( 'enabled': { 'blank': False, 'default': False, - 'field_type': models.IntegerField, + 'field_type': models.BooleanField, 'null': False, 'unique': False, }, diff --git a/app/project_management/tests/functional/project/conftest.py b/app/project_management/tests/functional/project/conftest.py new file mode 100644 index 00000000..31761261 --- /dev/null +++ b/app/project_management/tests/functional/project/conftest.py @@ -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 diff --git a/app/project_management/tests/functional/project/test_functional_project_api_fields.py b/app/project_management/tests/functional/project/test_functional_project_api_fields.py new file mode 100644 index 00000000..412a5c70 --- /dev/null +++ b/app/project_management/tests/functional/project/test_functional_project_api_fields.py @@ -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 diff --git a/app/project_management/tests/functional/project/test_project_viewset.py b/app/project_management/tests/functional/project/test_functional_project_metadata.py similarity index 79% rename from app/project_management/tests/functional/project/test_project_viewset.py rename to app/project_management/tests/functional/project/test_functional_project_metadata.py index 2b4ed54a..b41206ee 100644 --- a/app/project_management/tests/functional/project/test_project_viewset.py +++ b/app/project_management/tests/functional/project/test_functional_project_metadata.py @@ -3,15 +3,12 @@ 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 django.test import 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_permissions_viewset import APIPermissions -from api.tests.abstract.api_serializer_viewset import SerializersTestCases from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional 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: model = Project @@ -247,69 +245,7 @@ class ViewSetBase: -class ProjectPermissionsAPI(ViewSetBase, APIPermissions, TestCase): - - - 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 - - - +@pytest.mark.model_project class ProjectMetadata( ViewSetBase, MetaDataNavigationEntriesFunctional, diff --git a/app/project_management/tests/functional/project/test_functional_project_model.py b/app/project_management/tests/functional/project/test_functional_project_model.py new file mode 100644 index 00000000..b505744a --- /dev/null +++ b/app/project_management/tests/functional/project/test_functional_project_model.py @@ -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 diff --git a/app/project_management/tests/functional/project/test_project_serializer.py b/app/project_management/tests/functional/project/test_project_serializer.py deleted file mode 100644 index 24c8b98f..00000000 --- a/app/project_management/tests/functional/project/test_project_serializer.py +++ /dev/null @@ -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) - ) diff --git a/app/project_management/tests/functional/project_milestone/conftest.py b/app/project_management/tests/functional/project_milestone/conftest.py new file mode 100644 index 00000000..91a425d8 --- /dev/null +++ b/app/project_management/tests/functional/project_milestone/conftest.py @@ -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 diff --git a/app/project_management/tests/functional/project_milestone/test_functional_project_milestone_api_fields.py b/app/project_management/tests/functional/project_milestone/test_functional_project_milestone_api_fields.py new file mode 100644 index 00000000..32387837 --- /dev/null +++ b/app/project_management/tests/functional/project_milestone/test_functional_project_milestone_api_fields.py @@ -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 diff --git a/app/project_management/tests/functional/project_milestone/test_project_milestone_viewset.py b/app/project_management/tests/functional/project_milestone/test_functional_project_milestone_metadata.py similarity index 89% rename from app/project_management/tests/functional/project_milestone/test_project_milestone_viewset.py rename to app/project_management/tests/functional/project_milestone/test_functional_project_milestone_metadata.py index 3b7bba21..3418f468 100644 --- a/app/project_management/tests/functional/project_milestone/test_project_milestone_viewset.py +++ b/app/project_management/tests/functional/project_milestone/test_functional_project_milestone_metadata.py @@ -9,8 +9,6 @@ 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_permissions_viewset import APIPermissions -from api.tests.abstract.api_serializer_viewset import SerializersTestCases from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional 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: model = ProjectMilestone @@ -202,29 +201,7 @@ class ViewSetBase: -class ProjectMilestonePermissionsAPI(ViewSetBase, APIPermissions, TestCase): - - - 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 - - - +@pytest.mark.module_project_management class ProjectMilestoneMetadata( ViewSetBase, MetadataAttributesFunctional, diff --git a/app/project_management/tests/functional/project_milestone/test_functional_project_milestone_model.py b/app/project_management/tests/functional/project_milestone/test_functional_project_milestone_model.py new file mode 100644 index 00000000..4a6d9c2c --- /dev/null +++ b/app/project_management/tests/functional/project_milestone/test_functional_project_milestone_model.py @@ -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 diff --git a/app/project_management/tests/functional/project_milestone/test_project_milestone_serializer.py b/app/project_management/tests/functional/project_milestone/test_project_milestone_serializer.py deleted file mode 100644 index 53b5cff0..00000000 --- a/app/project_management/tests/functional/project_milestone/test_project_milestone_serializer.py +++ /dev/null @@ -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' - diff --git a/app/project_management/tests/functional/project_state/conftest.py b/app/project_management/tests/functional/project_state/conftest.py new file mode 100644 index 00000000..ee49e219 --- /dev/null +++ b/app/project_management/tests/functional/project_state/conftest.py @@ -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 diff --git a/app/project_management/tests/functional/project_state/test_functional_project_state_api_fields.py b/app/project_management/tests/functional/project_state/test_functional_project_state_api_fields.py new file mode 100644 index 00000000..63b3e5dd --- /dev/null +++ b/app/project_management/tests/functional/project_state/test_functional_project_state_api_fields.py @@ -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 diff --git a/app/project_management/tests/functional/project_state/test_project_state_viewset.py b/app/project_management/tests/functional/project_state/test_functional_project_state_metadata.py similarity index 95% rename from app/project_management/tests/functional/project_state/test_project_state_viewset.py rename to app/project_management/tests/functional/project_state/test_functional_project_state_metadata.py index 4d37cef2..6b67263b 100644 --- a/app/project_management/tests/functional/project_state/test_project_state_viewset.py +++ b/app/project_management/tests/functional/project_state/test_functional_project_state_metadata.py @@ -9,8 +9,6 @@ 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_permissions_viewset import APIPermissions -from api.tests.abstract.api_serializer_viewset import SerializersTestCases from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional 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: model = ProjectState @@ -216,18 +215,7 @@ class ViewSetBase: -class ProjectStatePermissionsAPI(ViewSetBase, APIPermissions, TestCase): - - pass - - - -class ProjectStateViewSet(ViewSetBase, SerializersTestCases, TestCase): - - pass - - - +@pytest.mark.module_project_management class ProjectStateMetadata( ViewSetBase, MetadataAttributesFunctional, diff --git a/app/project_management/tests/functional/project_state/test_functional_project_state_model.py b/app/project_management/tests/functional/project_state/test_functional_project_state_model.py new file mode 100644 index 00000000..b24a0a3a --- /dev/null +++ b/app/project_management/tests/functional/project_state/test_functional_project_state_model.py @@ -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 diff --git a/app/project_management/tests/functional/project_state/test_project_state_serializer.py b/app/project_management/tests/functional/project_state/test_project_state_serializer.py deleted file mode 100644 index ca115041..00000000 --- a/app/project_management/tests/functional/project_state/test_project_state_serializer.py +++ /dev/null @@ -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' diff --git a/app/project_management/tests/functional/project_type/conftest.py b/app/project_management/tests/functional/project_type/conftest.py new file mode 100644 index 00000000..9b4a8af5 --- /dev/null +++ b/app/project_management/tests/functional/project_type/conftest.py @@ -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 diff --git a/app/project_management/tests/functional/project_type/test_functional_project_type_api_fields.py b/app/project_management/tests/functional/project_type/test_functional_project_type_api_fields.py new file mode 100644 index 00000000..f751896e --- /dev/null +++ b/app/project_management/tests/functional/project_type/test_functional_project_type_api_fields.py @@ -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 diff --git a/app/project_management/tests/functional/project_type/test_project_type_viewset.py b/app/project_management/tests/functional/project_type/test_functional_project_type_metadata.py similarity index 97% rename from app/project_management/tests/functional/project_type/test_project_type_viewset.py rename to app/project_management/tests/functional/project_type/test_functional_project_type_metadata.py index 2efa27ee..5d50663a 100644 --- a/app/project_management/tests/functional/project_type/test_project_type_viewset.py +++ b/app/project_management/tests/functional/project_type/test_functional_project_type_metadata.py @@ -21,6 +21,7 @@ User = django.contrib.auth.get_user_model() +@pytest.mark.model_projecttype class ViewSetBase: model = ProjectType @@ -215,18 +216,7 @@ class ViewSetBase: -class ProjectTypePermissionsAPI(ViewSetBase, APIPermissions, TestCase): - - pass - - - -class ProjectTypeViewSet(ViewSetBase, SerializersTestCases, TestCase): - - pass - - - +@pytest.mark.module_project_management class ProjectTypeMetadata( ViewSetBase, MetadataAttributesFunctional, diff --git a/app/project_management/tests/functional/project_type/test_functional_project_type_model.py b/app/project_management/tests/functional/project_type/test_functional_project_type_model.py new file mode 100644 index 00000000..3ed2fba7 --- /dev/null +++ b/app/project_management/tests/functional/project_type/test_functional_project_type_model.py @@ -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 diff --git a/app/project_management/tests/functional/project_type/test_project_type_serializer.py b/app/project_management/tests/functional/project_type/test_project_type_serializer.py deleted file mode 100644 index de6f988a..00000000 --- a/app/project_management/tests/functional/project_type/test_project_type_serializer.py +++ /dev/null @@ -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' diff --git a/app/project_management/tests/unit/project/conftest.py b/app/project_management/tests/unit/project/conftest.py index a6af20d6..31761261 100644 --- a/app/project_management/tests/unit/project/conftest.py +++ b/app/project_management/tests/unit/project/conftest.py @@ -17,3 +17,9 @@ def model_kwargs(request, kwargs_project): 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 diff --git a/app/project_management/tests/unit/project/test_project_api_v2.py b/app/project_management/tests/unit/project/test_project_api_v2.py deleted file mode 100644 index e0bb9105..00000000 --- a/app/project_management/tests/unit/project/test_project_api_v2.py +++ /dev/null @@ -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 diff --git a/app/project_management/tests/unit/project/test_unit_project_model.py b/app/project_management/tests/unit/project/test_unit_project_model.py index 55054c82..f6dcd8fa 100644 --- a/app/project_management/tests/unit/project/test_unit_project_model.py +++ b/app/project_management/tests/unit/project/test_unit_project_model.py @@ -142,7 +142,7 @@ class ClusterModelTestCases( 'team_members': { 'blank': True, 'default': models.fields.NOT_PROVIDED, - 'field_type': models.ForeignKey, + 'field_type': models.ManyToManyField, 'null': False, 'unique': False, }, diff --git a/app/project_management/tests/unit/project/test_unit_project_serializer.py b/app/project_management/tests/unit/project/test_unit_project_serializer.py new file mode 100644 index 00000000..2d15201a --- /dev/null +++ b/app/project_management/tests/unit/project/test_unit_project_serializer.py @@ -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 \ No newline at end of file diff --git a/app/project_management/tests/unit/project/test_unit_project_viewset.py b/app/project_management/tests/unit/project/test_unit_project_viewset.py index 61e30927..1857de00 100644 --- a/app/project_management/tests/unit/project/test_unit_project_viewset.py +++ b/app/project_management/tests/unit/project/test_unit_project_viewset.py @@ -1,46 +1,88 @@ 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 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.module_project_management -class ProjectViewsetList( +class ViewsetTestCases( ModelViewSetInheritedCases, - TestCase, ): - viewset = ViewSet - route_name = 'v2:_api_project' + @pytest.fixture( scope = 'function' ) + def viewset(self): + return ViewSet - @classmethod - def setUpTestData(self): - """Setup Test - - 1. make list request - """ + @property + def parameterized_class_attributes(self): + return { + '_model_documentation': { + '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( - self.route_name + '-list', - kwargs = self.kwargs - ) +@pytest.mark.module_project_management +class ProjectViewsetPyTest( + ViewsetTestCases, +): - client.force_login(self.view_user) - - self.http_options_response_list = client.options(url) + pass diff --git a/app/project_management/tests/unit/project_milestone/conftest.py b/app/project_management/tests/unit/project_milestone/conftest.py index cc84246d..91a425d8 100644 --- a/app/project_management/tests/unit/project_milestone/conftest.py +++ b/app/project_management/tests/unit/project_milestone/conftest.py @@ -17,3 +17,9 @@ def model_kwargs(request, kwargs_projectmilestone): 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 diff --git a/app/project_management/tests/unit/project_milestone/test_project_milestone_api_v2.py b/app/project_management/tests/unit/project_milestone/test_project_milestone_api_v2.py deleted file mode 100644 index 2d164f80..00000000 --- a/app/project_management/tests/unit/project_milestone/test_project_milestone_api_v2.py +++ /dev/null @@ -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 diff --git a/app/project_management/tests/unit/project_milestone/test_unit_projectmilestone_model.py b/app/project_management/tests/unit/project_milestone/test_unit_project_milestone_model.py similarity index 100% rename from app/project_management/tests/unit/project_milestone/test_unit_projectmilestone_model.py rename to app/project_management/tests/unit/project_milestone/test_unit_project_milestone_model.py diff --git a/app/project_management/tests/unit/project_milestone/test_unit_project_milestone_serializer.py b/app/project_management/tests/unit/project_milestone/test_unit_project_milestone_serializer.py new file mode 100644 index 00000000..82f1da29 --- /dev/null +++ b/app/project_management/tests/unit/project_milestone/test_unit_project_milestone_serializer.py @@ -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 \ No newline at end of file diff --git a/app/project_management/tests/unit/project_milestone/test_unit_project_milestone_viewset.py b/app/project_management/tests/unit/project_milestone/test_unit_project_milestone_viewset.py index 9d4249ef..0be85ce1 100644 --- a/app/project_management/tests/unit/project_milestone/test_unit_project_milestone_viewset.py +++ b/app/project_management/tests/unit/project_milestone/test_unit_project_milestone_viewset.py @@ -1,54 +1,130 @@ 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 project_management.models.projects import Project -from project_management.viewsets.project_milestone import ViewSet +from project_management.viewsets.project_milestone import ( + ProjectMilestone, + ViewSet, +) -@pytest.mark.skip(reason = 'see #895, tests being refactored') @pytest.mark.model_projectmilestone -@pytest.mark.module_project_management -class ProjectMilestoneViewsetList( +class ViewsetTestCases( ModelViewSetInheritedCases, - TestCase, ): - viewset = ViewSet - route_name = 'v2:_api_projectmilestone' + @pytest.fixture( scope = 'function' ) + def viewset(self): + return ViewSet - @classmethod - def setUpTestData(self): - """Setup Test - - 1. make list request - """ - - - super().setUpTestData() - - self.kwargs = { - 'project_id': Project.objects.create( - organization = self.organization, - name = 'proj' - ).id + @property + def parameterized_class_attributes(self): + return { + '_model_documentation': { + 'type': type(None), + }, + 'back_url': { + 'type': type(None), + }, + 'documentation': { + 'type': type(None), + 'value': None + }, + 'filterset_fields': { + '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() - - url = reverse( - self.route_name + '-list', - kwargs = self.kwargs - ) + def test_view_func_get_queryset_cache_result(self, viewset_mock_request, + model_kwargs + ): + """Viewset Test - client.force_login(self.view_user) + Ensure that the `get_queryset` function caches the result under + attribute `.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 `.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 diff --git a/app/project_management/tests/unit/project_state/conftest.py b/app/project_management/tests/unit/project_state/conftest.py index 7f71fa8f..ee49e219 100644 --- a/app/project_management/tests/unit/project_state/conftest.py +++ b/app/project_management/tests/unit/project_state/conftest.py @@ -17,3 +17,9 @@ def model_kwargs(request, kwargs_projectstate): 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 diff --git a/app/project_management/tests/unit/project_state/test_project_state_api_v2.py b/app/project_management/tests/unit/project_state/test_project_state_api_v2.py deleted file mode 100644 index 3fe5484f..00000000 --- a/app/project_management/tests/unit/project_state/test_project_state_api_v2.py +++ /dev/null @@ -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 diff --git a/app/project_management/tests/unit/project_state/test_unit_project_state_serializer.py b/app/project_management/tests/unit/project_state/test_unit_project_state_serializer.py new file mode 100644 index 00000000..a05249b6 --- /dev/null +++ b/app/project_management/tests/unit/project_state/test_unit_project_state_serializer.py @@ -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 \ No newline at end of file diff --git a/app/project_management/tests/unit/project_state/test_unit_project_state_viewset.py b/app/project_management/tests/unit/project_state/test_unit_project_state_viewset.py index d7f51853..c18b83cc 100644 --- a/app/project_management/tests/unit/project_state/test_unit_project_state_viewset.py +++ b/app/project_management/tests/unit/project_state/test_unit_project_state_viewset.py @@ -1,45 +1,83 @@ 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 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.module_project_management -class ProjectStateViewsetList( +class ViewsetTestCases( ModelViewSetInheritedCases, - TestCase, ): - viewset = ViewSet - route_name = 'v2:_api_projectstate' + @pytest.fixture( scope = 'function' ) + def viewset(self): + return ViewSet - @classmethod - def setUpTestData(self): - """Setup Test - - 1. make list request - """ - - super().setUpTestData() + @property + def parameterized_class_attributes(self): + return { + '_model_documentation': { + 'type': type(None), + }, + 'back_url': { + '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 diff --git a/app/project_management/tests/unit/project_type/conftest.py b/app/project_management/tests/unit/project_type/conftest.py index a6299180..9b4a8af5 100644 --- a/app/project_management/tests/unit/project_type/conftest.py +++ b/app/project_management/tests/unit/project_type/conftest.py @@ -17,3 +17,9 @@ def model_kwargs(request, kwargs_projecttype): 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 diff --git a/app/project_management/tests/unit/project_type/test_project_type_api_v2.py b/app/project_management/tests/unit/project_type/test_project_type_api_v2.py deleted file mode 100644 index 5b12fdf2..00000000 --- a/app/project_management/tests/unit/project_type/test_project_type_api_v2.py +++ /dev/null @@ -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 diff --git a/app/project_management/tests/unit/project_type/test_unit_project_type_serializer.py b/app/project_management/tests/unit/project_type/test_unit_project_type_serializer.py new file mode 100644 index 00000000..d5fd19d3 --- /dev/null +++ b/app/project_management/tests/unit/project_type/test_unit_project_type_serializer.py @@ -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 \ No newline at end of file diff --git a/app/project_management/tests/unit/project_type/test_unit_project_type_viewset.py b/app/project_management/tests/unit/project_type/test_unit_project_type_viewset.py index 0fb4deb4..09e91c1e 100644 --- a/app/project_management/tests/unit/project_type/test_unit_project_type_viewset.py +++ b/app/project_management/tests/unit/project_type/test_unit_project_type_viewset.py @@ -1,46 +1,83 @@ 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 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.module_project_management -class ProjectTypeViewsetList( +class ViewsetTestCases( ModelViewSetInheritedCases, - TestCase, ): - viewset = ViewSet - route_name = 'v2:_api_projecttype' + @pytest.fixture( scope = 'function' ) + def viewset(self): + return ViewSet - @classmethod - def setUpTestData(self): - """Setup Test - - 1. make list request - """ + @property + def parameterized_class_attributes(self): + return { + '_model_documentation': { + '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( - self.route_name + '-list', - kwargs = self.kwargs - ) +@pytest.mark.module_project_management +class ProjectTypeViewsetPyTest( + ViewsetTestCases, +): - client.force_login(self.view_user) - - self.http_options_response_list = client.options(url) + pass diff --git a/app/settings/tests/unit/app_settings/test_unit_app_settings_model.py b/app/settings/tests/unit/app_settings/test_unit_app_settings_model.py index 38abfdd1..b7c491ea 100644 --- a/app/settings/tests/unit/app_settings/test_unit_app_settings_model.py +++ b/app/settings/tests/unit/app_settings/test_unit_app_settings_model.py @@ -36,14 +36,14 @@ class AppSettingsModelTestCases( 'model_notes': { 'blank': models.fields.NOT_PROVIDED, 'default': models.fields.NOT_PROVIDED, - 'field_type': models.CharField, + 'field_type': models.fields.NOT_PROVIDED, 'null': models.fields.NOT_PROVIDED, 'unique': models.fields.NOT_PROVIDED, }, 'organization': { 'blank': models.fields.NOT_PROVIDED, 'default': models.fields.NOT_PROVIDED, - 'field_type': models.CharField, + 'field_type': models.fields.NOT_PROVIDED, 'null': models.fields.NOT_PROVIDED, 'unique': models.fields.NOT_PROVIDED, }, diff --git a/app/settings/tests/unit/user_settings/test_unit_user_settings_model.py b/app/settings/tests/unit/user_settings/test_unit_user_settings_model.py index 5ed1082c..2a27ce87 100644 --- a/app/settings/tests/unit/user_settings/test_unit_user_settings_model.py +++ b/app/settings/tests/unit/user_settings/test_unit_user_settings_model.py @@ -43,14 +43,14 @@ class UserSettingsModelTestCases( 'model_notes': { 'blank': models.fields.NOT_PROVIDED, 'default': models.fields.NOT_PROVIDED, - 'field_type': models.CharField, + 'field_type': models.fields.NOT_PROVIDED, 'null': models.fields.NOT_PROVIDED, 'unique': models.fields.NOT_PROVIDED, }, 'organization': { 'blank': models.fields.NOT_PROVIDED, 'default': models.fields.NOT_PROVIDED, - 'field_type': models.CharField, + 'field_type': models.fields.NOT_PROVIDED, 'null': models.fields.NOT_PROVIDED, 'unique': models.fields.NOT_PROVIDED, }, diff --git a/app/tests/fixtures/__init__.py b/app/tests/fixtures/__init__.py index 49ced6b8..2c6d424a 100644 --- a/app/tests/fixtures/__init__.py +++ b/app/tests/fixtures/__init__.py @@ -236,21 +236,25 @@ from .model_port import ( from .model_project import ( kwargs_project, model_project, + serializer_project, ) from .model_projectmilestone import ( kwargs_projectmilestone, model_projectmilestone, + serializer_projectmilestone, ) from .model_projectstate import ( kwargs_projectstate, model_projectstate, + serializer_projectstate, ) from .model_projecttype import ( kwargs_projecttype, model_projecttype, + serializer_projecttype, ) from .model_requestticket import ( diff --git a/app/tests/fixtures/model_knowledgebase.py b/app/tests/fixtures/model_knowledgebase.py index c18dc2fd..c2ff9fcc 100644 --- a/app/tests/fixtures/model_knowledgebase.py +++ b/app/tests/fixtures/model_knowledgebase.py @@ -1,6 +1,8 @@ import datetime import pytest +from django.db import models + from assistance.models.knowledge_base import KnowledgeBase from assistance.serializers.knowledge_base import ( KnowledgeBaseBaseSerializer, @@ -66,10 +68,14 @@ def kwargs_knowledgebase(django_db_blocker, try: user.delete() - except: + except models.deletion.ProtectedError: + pass + + try: + category.delete() + except models.deletion.ProtectedError: pass - category.delete() @pytest.fixture( scope = 'class') diff --git a/app/tests/fixtures/model_project.py b/app/tests/fixtures/model_project.py index 0ef6d923..026a30ac 100644 --- a/app/tests/fixtures/model_project.py +++ b/app/tests/fixtures/model_project.py @@ -1,7 +1,16 @@ import datetime import pytest +import random + +from django.db import models 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') -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(random_str).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() del kwargs['model_notes'] kwargs = { **kwargs, + 'code': 'aCODE', 'name': 'project_' + random_str, + 'description': 'a description', '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() + + 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 + } diff --git a/app/tests/fixtures/model_projectmilestone.py b/app/tests/fixtures/model_projectmilestone.py index ba97f8c8..4fe77234 100644 --- a/app/tests/fixtures/model_projectmilestone.py +++ b/app/tests/fixtures/model_projectmilestone.py @@ -1,7 +1,14 @@ import datetime import pytest +from django.db import models + 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(): - 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({ 'name': 'pm' + random_str }) + del kwargs['code'] project = model_project.objects.create( **kwargs ) + kwargs = kwargs_centurionmodel.copy() del kwargs['model_notes'] @@ -38,6 +69,8 @@ def kwargs_projectmilestone(django_db_blocker, **kwargs, 'name': 'pm_' + random_str, 'project': project, + 'start_date': '2025-08-04T00:00:01Z', + 'finish_date': '2025-08-04T00:00:02Z', } yield kwargs.copy() @@ -45,3 +78,13 @@ def kwargs_projectmilestone(django_db_blocker, # with django_db_blocker.unblock(): # project.delete() # milestone is cascade delete + + +@pytest.fixture( scope = 'class') +def serializer_projectmilestone(): + + yield { + 'base': ProjectMilestoneBaseSerializer, + 'model': ProjectMilestoneModelSerializer, + 'view': ProjectMilestoneViewSerializer + } diff --git a/app/tests/fixtures/model_projectstate.py b/app/tests/fixtures/model_projectstate.py index f3fce986..671dfe6b 100644 --- a/app/tests/fixtures/model_projectstate.py +++ b/app/tests/fixtures/model_projectstate.py @@ -1,8 +1,14 @@ import datetime 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') @@ -12,18 +18,47 @@ def model_projectstate(): @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(random_str).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() - del kwargs['model_notes'] kwargs = { **kwargs, 'name': 'projectstate_' + random_str, + 'runbook': runbook, } 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 + } diff --git a/app/tests/fixtures/model_projecttype.py b/app/tests/fixtures/model_projecttype.py index 25673f32..8f130e01 100644 --- a/app/tests/fixtures/model_projecttype.py +++ b/app/tests/fixtures/model_projecttype.py @@ -1,7 +1,14 @@ import datetime import pytest +from django.db import models + 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') -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(random_str).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(), 'name': 'projecttype_' + random_str, + 'runbook': runbook, } 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 + }