Skip to content

Commit

Permalink
add api view tests (#1090)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Jan 23, 2025
1 parent f48cef1 commit 7861d5c
Show file tree
Hide file tree
Showing 3 changed files with 311 additions and 7 deletions.
2 changes: 1 addition & 1 deletion projectroles/tests/test_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1017,7 +1017,7 @@ def test_get_category_anon(self):
self.assert_response(self.url_cat, self.user_no_roles, 302)

def test_get_remote_not_revoked(self):
"""Test GET with non-revoked remote project as target site"""
"""Test GET with non-revoked remote project"""
site = self.make_site(
name=REMOTE_SITE_NAME,
url=REMOTE_SITE_URL,
Expand Down
279 changes: 279 additions & 0 deletions projectroles/tests/test_permissions_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
ProjectInvite,
SODAR_CONSTANTS,
)
from projectroles.tests.test_models import RemoteSiteMixin, RemoteProjectMixin
from projectroles.tests.test_permissions import ProjectPermissionTestBase
from projectroles.tests.test_views_api import SODARAPIViewTestMixin
from projectroles.utils import build_secret
from projectroles.views_api import (
PROJECTROLES_API_MEDIA_TYPE,
PROJECTROLES_API_DEFAULT_VERSION,
Expand All @@ -21,7 +23,19 @@
from rest_framework.test import APITestCase


# SODAR constants
PROJECT_TYPE_PROJECT = SODAR_CONSTANTS['PROJECT_TYPE_PROJECT']
PROJECT_TYPE_CATEGORY = SODAR_CONSTANTS['PROJECT_TYPE_CATEGORY']
SITE_MODE_SOURCE = SODAR_CONSTANTS['SITE_MODE_SOURCE']
SITE_MODE_TARGET = SODAR_CONSTANTS['SITE_MODE_TARGET']
REMOTE_LEVEL_READ_ROLES = SODAR_CONSTANTS['REMOTE_LEVEL_READ_ROLES']
REMOTE_LEVEL_REVOKED = SODAR_CONSTANTS['REMOTE_LEVEL_REVOKED']

# Local constants
NEW_PROJECT_TITLE = 'New Project'
REMOTE_SITE_NAME = 'Test site'
REMOTE_SITE_URL = 'https://sodar.bihealth.org'
REMOTE_SITE_SECRET = build_secret()


# Base Classes and Mixins ------------------------------------------------------
Expand Down Expand Up @@ -514,6 +528,271 @@ def test_put_read_only(self):
)


class TestProjectDestroyAPIView(
RemoteSiteMixin, RemoteProjectMixin, ProjectrolesAPIPermissionTestBase
):
"""Tests for ProjectDestroyAPIView permissions"""

def _cleanup(self, make_project=True):
if not Project.objects.filter(sodar_uuid=self.cat_uuid).first():
self.category = self.make_project(
title='TestCategory',
type=PROJECT_TYPE_CATEGORY,
parent=None,
sodar_uuid=self.cat_uuid,
)
self.make_assignment(
self.category, self.user_owner_cat, self.role_owner
)
self.make_assignment(
self.category, self.user_delegate_cat, self.role_delegate
)
self.make_assignment(
self.category, self.user_contributor_cat, self.role_contributor
)
self.make_assignment(
self.category, self.user_guest_cat, self.role_guest
)
self.make_assignment(
self.category, self.user_finder_cat, self.role_finder
)
if (
make_project
and not Project.objects.filter(sodar_uuid=self.project_uuid).first()
):
self.project = self.make_project(
title='TestProject',
type=PROJECT_TYPE_PROJECT,
parent=self.category,
sodar_uuid=self.project_uuid,
)
self.make_assignment(self.project, self.user_owner, self.role_owner)
self.make_assignment(
self.project, self.user_delegate, self.role_delegate
)
self.make_assignment(
self.project, self.user_contributor, self.role_contributor
)
self.make_assignment(self.project, self.user_guest, self.role_guest)

def setUp(self):
super().setUp()
self.project_uuid = self.project.sodar_uuid
self.cat_uuid = self.category.sodar_uuid
self.url = reverse(
'projectroles:api_project_destroy',
kwargs={'project': self.project.sodar_uuid},
)
self.url_cat = reverse(
'projectroles:api_project_destroy',
kwargs={'project': self.category.sodar_uuid},
)
self.good_users = [
self.superuser,
self.user_owner_cat,
self.user_delegate_cat,
self.user_owner,
self.user_delegate,
]
self.bad_users = [
self.user_contributor_cat,
self.user_guest_cat,
self.user_finder_cat,
self.user_contributor,
self.user_guest,
self.user_no_roles,
]
self.good_users_cat = [
self.superuser,
self.user_owner_cat,
self.user_delegate_cat,
]
self.bad_users_cat = [
self.user_contributor_cat,
self.user_guest_cat,
self.user_finder_cat,
self.user_owner,
self.user_delegate,
self.user_contributor,
self.user_guest,
self.user_no_roles,
]

def test_delete(self):
"""Test RoleAssignmentDestroyAPIView DELETE"""
self.assert_response_api(
self.url,
self.good_users,
204,
method='DELETE',
cleanup_method=self._cleanup,
)
self.assert_response_api(self.url, self.bad_users, 403, method='DELETE')
self.assert_response_api(self.url, self.anonymous, 401, method='DELETE')
self.assert_response_api(
self.url,
self.good_users,
204,
method='DELETE',
cleanup_method=self._cleanup,
knox=True,
)
self.assert_response_api(
self.url, self.bad_users, 403, method='DELETE', knox=True
)
self.project.set_public()
self.assert_response_api(
self.url, self.user_no_roles, 403, method='DELETE'
)

def test_delete_category_with_children(self):
"""Test DELETE for category with children (should fail)"""
self.assert_response_api(
self.url_cat,
self.auth_users,
403,
method='DELETE',
)
self.assert_response_api(
self.url_cat, self.anonymous, 401, method='DELETE'
)
self.project.set_public()
self.assert_response_api(
self.url_cat, self.user_no_roles, 403, method='DELETE'
)

def test_delete_category_without_children(self):
"""Test DELETE for category without children"""
self.project.delete()
self.assert_response_api(
self.url_cat,
self.good_users_cat,
204,
method='DELETE',
cleanup_method=self._cleanup,
cleanup_kwargs={'make_project': False},
)
self.assert_response_api(
self.url_cat,
self.bad_users_cat,
403,
method='DELETE',
)
self.assert_response_api(
self.url_cat, self.anonymous, 401, method='DELETE'
)

def test_delete_remote(self):
"""Test DELETE with non-revoked remote project (should fail)"""
site = self.make_site(
name=REMOTE_SITE_NAME,
url=REMOTE_SITE_URL,
mode=SITE_MODE_TARGET,
description='',
secret=REMOTE_SITE_SECRET,
)
self.make_remote_project(
project_uuid=self.project.sodar_uuid,
project=self.project,
site=site,
level=REMOTE_LEVEL_READ_ROLES,
)
self.assert_response_api(
self.url_cat,
self.auth_users,
403,
method='DELETE',
)
self.assert_response_api(
self.url_cat, self.anonymous, 401, method='DELETE'
)
self.project.set_public()
self.assert_response_api(
self.url_cat, self.user_no_roles, 403, method='DELETE'
)

def test_delete_remote_revoked(self):
"""Test DELETE with revoked remote project"""
site = self.make_site(
name=REMOTE_SITE_NAME,
url=REMOTE_SITE_URL,
mode=SITE_MODE_TARGET,
description='',
secret=REMOTE_SITE_SECRET,
)
self.make_remote_project(
project_uuid=self.project.sodar_uuid,
project=self.project,
site=site,
level=REMOTE_LEVEL_REVOKED,
)
self.assert_response_api(
self.url,
self.good_users,
204,
method='DELETE',
cleanup_method=self._cleanup,
)
self.assert_response_api(self.url, self.bad_users, 403, method='DELETE')
self.assert_response_api(self.url, self.anonymous, 401, method='DELETE')

@override_settings(PROJECTROLES_SITE_MODE=SITE_MODE_TARGET)
def test_delete_remote_target(self):
"""Test DELETE with non-revoked remote project as target site (should fail)"""
site = self.make_site(
name=REMOTE_SITE_NAME,
url=REMOTE_SITE_URL,
mode=SITE_MODE_SOURCE,
description='',
secret=REMOTE_SITE_SECRET,
)
self.make_remote_project(
project_uuid=self.project.sodar_uuid,
project=self.project,
site=site,
level=REMOTE_LEVEL_READ_ROLES,
)
self.assert_response_api(
self.url_cat,
self.auth_users,
403,
method='DELETE',
)
self.assert_response_api(
self.url_cat, self.anonymous, 401, method='DELETE'
)
self.project.set_public()
self.assert_response_api(
self.url_cat, self.user_no_roles, 403, method='DELETE'
)

@override_settings(PROJECTROLES_SITE_MODE=SITE_MODE_TARGET)
def test_delete_remote_revoked_target(self):
"""Test DELETE with revoked remote project as target site"""
site = self.make_site(
name=REMOTE_SITE_NAME,
url=REMOTE_SITE_URL,
mode=SITE_MODE_SOURCE,
description='',
secret=REMOTE_SITE_SECRET,
)
self.make_remote_project(
project_uuid=self.project.sodar_uuid,
project=self.project,
site=site,
level=REMOTE_LEVEL_REVOKED,
)
self.assert_response_api(
self.url,
self.good_users,
204,
method='DELETE',
cleanup_method=self._cleanup,
)
self.assert_response_api(self.url, self.bad_users, 403, method='DELETE')
self.assert_response_api(self.url, self.anonymous, 401, method='DELETE')


class TestRoleAssignmentCreateAPIView(ProjectrolesAPIPermissionTestBase):
"""Tests for RoleAssignmentCreateAPIView permissions"""

Expand Down
37 changes: 31 additions & 6 deletions projectroles/tests/test_views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
SODAR_CONSTANTS,
CAT_DELIMITER,
)
from projectroles.plugins import get_backend_api
from projectroles.remote_projects import RemoteProjectAPI
from projectroles.tests.test_app_settings import AppSettingInitMixin
from projectroles.tests.test_models import (
Expand Down Expand Up @@ -1336,8 +1337,16 @@ class TestProjectDestroyAPIView(
):
"""Tests for ProjectDestroyAPIView"""

@classmethod
def _get_delete_tl(cls):
return TimelineEvent.objects.filter(event_name='project_delete')

def _get_delete_alerts(self):
return self.app_alert_model.objects.filter(alert_name='project_delete')

def setUp(self):
super().setUp()
self.app_alert_model = get_backend_api('appalerts_backend').get_model()
self.url = reverse(
'projectroles:api_project_destroy',
kwargs={'project': self.project.sodar_uuid},
Expand All @@ -1350,16 +1359,32 @@ def setUp(self):
def test_delete(self):
"""Test ProjectDestroyAPIView DELETE"""
self.assertEqual(Project.objects.count(), 2)
self.assertEqual(self._get_delete_tl().count(), 0)
self.assertEqual(self._get_delete_alerts().count(), 0)
self.assertEqual(len(mail.outbox), 0)

response = self.request_knox(self.url, method='DELETE')
self.assertEqual(response.status_code, 204, msg=response.content)
self.assertEqual(Project.objects.count(), 1)
self.assertIsNone(
Project.objects.filter(sodar_uuid=self.project.sodar_uuid).first(),
None,
)
self.assertEqual(self._get_delete_tl().count(), 1)
alerts = self._get_delete_alerts()
self.assertEqual(alerts.count(), 2)
self.assertEqual(
sorted([a.user.username for a in alerts]),
sorted(['user_owner', 'user_owner_cat']),
)
self.assertEqual(len(mail.outbox), 2)

# TODO: Test with category with children (should fail)
# TODO: Test with category without children
# TODO: Test with source project and non-revoked remote project (should fail)
# TODO: Test with source project and revoked remote project
# TODO: Test with target project and non-revoked remote project (should fail)
# TODO: Test with target project and revoked remote project
def test_delete_v1_0(self):
"""Test DELETE with API version 1.0 (should fail)"""
self.assertEqual(Project.objects.count(), 2)
response = self.request_knox(self.url, method='DELETE', version='1.0')
self.assertEqual(response.status_code, 406, msg=response.content)
self.assertEqual(Project.objects.count(), 2)


class TestRoleAssignmentCreateAPIView(
Expand Down

0 comments on commit 7861d5c

Please sign in to comment.