From 0320c92dd6ff7f9ef8bddd808d168c038cf38c58 Mon Sep 17 00:00:00 2001
From: Jochen Klar
Date: Mon, 30 Mar 2026 21:25:03 +0200
Subject: [PATCH 01/16] Remove project views and tests
---
rdmo/projects/tests/test_export.py | 29 -
rdmo/projects/tests/test_view_integration.py | 240 -----
rdmo/projects/tests/test_view_issue.py | 226 -----
rdmo/projects/tests/test_view_membership.py | 301 ------
.../tests/test_view_membership_multisite.py | 106 ---
rdmo/projects/tests/test_view_project.py | 896 ------------------
rdmo/projects/tests/test_view_project_copy.py | 207 ----
.../tests/test_view_project_create_import.py | 359 -------
.../projects/tests/test_view_project_leave.py | 146 ---
.../tests/test_view_project_update_import.py | 471 ---------
.../test_view_project_update_visibility.py | 412 --------
.../tests/test_view_project_visibility.py | 147 ---
rdmo/projects/tests/test_view_snapshot.py | 229 -----
rdmo/projects/tests/test_views.py | 76 ++
rdmo/projects/tests/test_viewset_project.py | 27 +-
rdmo/projects/urls/__init__.py | 141 +--
rdmo/projects/views.py | 79 ++
rdmo/projects/views/__init__.py | 31 -
rdmo/projects/views/integration.py | 92 --
rdmo/projects/views/invite.py | 22 -
rdmo/projects/views/issue.py | 197 ----
rdmo/projects/views/membership.py | 95 --
rdmo/projects/views/project.py | 223 -----
rdmo/projects/views/project_answers.py | 87 --
rdmo/projects/views/project_copy.py | 39 -
rdmo/projects/views/project_create.py | 85 --
rdmo/projects/views/project_update.py | 196 ----
rdmo/projects/views/project_view.py | 100 --
rdmo/projects/views/snapshot.py | 96 --
29 files changed, 172 insertions(+), 5183 deletions(-)
delete mode 100644 rdmo/projects/tests/test_export.py
delete mode 100644 rdmo/projects/tests/test_view_integration.py
delete mode 100644 rdmo/projects/tests/test_view_issue.py
delete mode 100644 rdmo/projects/tests/test_view_membership.py
delete mode 100644 rdmo/projects/tests/test_view_membership_multisite.py
delete mode 100644 rdmo/projects/tests/test_view_project.py
delete mode 100644 rdmo/projects/tests/test_view_project_copy.py
delete mode 100644 rdmo/projects/tests/test_view_project_create_import.py
delete mode 100644 rdmo/projects/tests/test_view_project_leave.py
delete mode 100644 rdmo/projects/tests/test_view_project_update_import.py
delete mode 100644 rdmo/projects/tests/test_view_project_update_visibility.py
delete mode 100644 rdmo/projects/tests/test_view_project_visibility.py
delete mode 100644 rdmo/projects/tests/test_view_snapshot.py
create mode 100644 rdmo/projects/tests/test_views.py
create mode 100644 rdmo/projects/views.py
delete mode 100644 rdmo/projects/views/__init__.py
delete mode 100644 rdmo/projects/views/integration.py
delete mode 100644 rdmo/projects/views/invite.py
delete mode 100644 rdmo/projects/views/issue.py
delete mode 100644 rdmo/projects/views/membership.py
delete mode 100644 rdmo/projects/views/project.py
delete mode 100644 rdmo/projects/views/project_answers.py
delete mode 100644 rdmo/projects/views/project_copy.py
delete mode 100644 rdmo/projects/views/project_create.py
delete mode 100644 rdmo/projects/views/project_update.py
delete mode 100644 rdmo/projects/views/project_view.py
delete mode 100644 rdmo/projects/views/snapshot.py
diff --git a/rdmo/projects/tests/test_export.py b/rdmo/projects/tests/test_export.py
deleted file mode 100644
index d52d0bfa37..0000000000
--- a/rdmo/projects/tests/test_export.py
+++ /dev/null
@@ -1,29 +0,0 @@
-import os
-
-from django.conf import settings
-from django.urls import reverse
-
-# def test_project_answers_export_html(db, client):
-# client.login(username='admin', password='admin')
-
-# url = reverse('project_answers_export', args=[1, 'html'])
-# response = client.get(url)
-
-# assert response.status_code == 200
-
-# test_file = os.path.join(settings.BASE_DIR, 'export', 'project.html')
-# for a, b in zip(response.content.decode().splitlines(), open(test_file).read().splitlines(), strict=True):
-# assert a == b
-
-
-def test_project_export_csv(db, client):
- client.login(username='admin', password='admin')
-
- url = reverse('project_export', args=[1, 'csvcomma'])
- response = client.get(url)
-
- assert response.status_code == 200
-
- test_file = os.path.join(settings.BASE_DIR, 'export', 'project.csv')
- for a, b in zip(response.content.decode().splitlines(), open(test_file).read().splitlines(), strict=True):
- assert a == b
diff --git a/rdmo/projects/tests/test_view_integration.py b/rdmo/projects/tests/test_view_integration.py
deleted file mode 100644
index 711b7790ee..0000000000
--- a/rdmo/projects/tests/test_view_integration.py
+++ /dev/null
@@ -1,240 +0,0 @@
-import pytest
-
-from django.urls import reverse
-
-from ..models import Integration, Issue
-
-users = (
- ('owner', 'owner'),
- ('manager', 'manager'),
- ('author', 'author'),
- ('guest', 'guest'),
- ('user', 'user'),
- ('site', 'site'),
- ('anonymous', None),
-)
-
-add_integration_permission_map = change_integration_permission_map = delete_integration_permission_map = {
- 'owner': [1, 2, 3, 4, 5],
- 'manager': [1, 3, 5],
- 'api': [1, 2, 3, 4, 5],
- 'site': [1, 2, 3, 4, 5]
-}
-
-projects = [1, 2, 3, 4, 5]
-integrations = [1, 2]
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-def test_integration_create_get(db, client, username, password, project_id):
- client.login(username=username, password=password)
-
- url = reverse('integration_create', args=[project_id, 'simple'])
- response = client.get(url)
-
- if project_id in add_integration_permission_map.get(username, []):
- assert response.status_code == 200
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-def test_integration_create_post(db, client, username, password, project_id):
- client.login(username=username, password=password)
-
- url = reverse('integration_create', args=[project_id, 'simple'])
- data = {
- 'project_url': 'https://example.com/projects/1'
- }
- response = client.post(url, data)
-
- if project_id in add_integration_permission_map.get(username, []):
- assert response.status_code == 302
- values = Integration.objects.order_by('id').last().options.values('key', 'value', 'secret')
- assert sorted(values, key=lambda obj: obj['key']) == [
- {
- 'key': 'project_url',
- 'value': 'https://example.com/projects/1',
- 'secret': False
- },
- {
- 'key': 'secret',
- 'value': '',
- 'secret': True
- }
- ]
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('integration_id', integrations)
-def test_integration_update_get(db, client, username, password, project_id, integration_id):
- client.login(username=username, password=password)
- integration = Integration.objects.filter(project_id=project_id, id=integration_id).first()
-
- url = reverse('integration_update', args=[project_id, integration_id])
- response = client.get(url)
-
- if integration:
- if project_id in change_integration_permission_map.get(username, []):
- assert response.status_code == 200
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
- else:
- assert response.status_code == 404
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('integration_id', integrations)
-def test_integration_update_post(db, client, username, password, project_id, integration_id):
- client.login(username=username, password=password)
- integration = Integration.objects.filter(project_id=project_id, id=integration_id).first()
-
- url = reverse('integration_update', args=[project_id, integration_id])
- data = {
- 'project_url': 'https://example.com/projects/2',
- 'secret': 'super_secret'
- }
- response = client.post(url, data)
-
- if integration:
- if project_id in change_integration_permission_map.get(username, []):
- assert response.status_code == 302
- values = Integration.objects.filter(project_id=project_id, id=integration_id).first() \
- .options.values('key', 'value', 'secret')
- assert sorted(values, key=lambda obj: obj['key']) == [
- {
- 'key': 'project_url',
- 'value': 'https://example.com/projects/2',
- 'secret': False
- },
- {
- 'key': 'secret',
- 'value': 'super_secret',
- 'secret': True
- }
- ]
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
- else:
- assert response.status_code == 404
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('integration_id', integrations)
-def test_integration_delete_get(db, client, username, password, project_id, integration_id):
- client.login(username=username, password=password)
- integration = Integration.objects.filter(project_id=project_id, id=integration_id).first()
-
- url = reverse('integration_delete', args=[project_id, integration_id])
- response = client.get(url)
-
- if integration:
- if project_id in delete_integration_permission_map.get(username, []):
- assert response.status_code == 200
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
- else:
- assert response.status_code == 404
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('integration_id', integrations)
-def test_integration_delete_post(db, client, username, password, project_id, integration_id):
- client.login(username=username, password=password)
- integration = Integration.objects.filter(project_id=project_id, id=integration_id).first()
-
- url = reverse('integration_delete', args=[project_id, integration_id])
- response = client.delete(url)
-
- if integration:
- if project_id in delete_integration_permission_map.get(username, []):
- assert response.status_code == 302
- assert Integration.objects.filter(project_id=project_id, id=integration_id).first() is None
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
- else:
- assert response.status_code == 404
-
-
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('integration_id', integrations)
-def test_integration_webhook_get(db, client, project_id, integration_id):
- url = reverse('integration_webhook', args=[project_id, integration_id])
- response = client.get(url)
-
- assert response.status_code == 405
- assert Issue.objects.filter(status='closed').count() == 0
-
-
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('integration_id', integrations)
-def test_integration_webhook_post(db, client, project_id, integration_id):
- integration = Integration.objects.filter(project_id=project_id, id=integration_id).first()
-
- secret = 'super_duper_secret'
- url = reverse('integration_webhook', args=[project_id, integration_id])
- data = {
- 'action': 'closed',
- 'url': 'https://simple.example.com/issues/1'
- }
-
- response = client.post(url, data, **{'HTTP_X_SECRET': secret, 'content_type': 'application/json'})
-
- if integration:
- assert response.status_code == 200
- assert Issue.objects.filter(status='closed').count() == (1 if integration_id == 1 else 0)
- else:
- assert response.status_code == 404
- assert Issue.objects.filter(status='closed').count() == 0
-
-
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('integration_id', integrations)
-def test_integration_webhook_post_wrong_url(db, client, project_id, integration_id):
- integration = Integration.objects.filter(project_id=project_id, id=integration_id).first()
-
- secret = 'super_duper_secret'
- url = reverse('integration_webhook', args=[project_id, integration_id])
- data = {
- 'action': 'closed',
- 'url': 'https://simple.example.com/issues/2'
- }
-
- response = client.post(url, data, **{'HTTP_X_SECRET': secret, 'content_type': 'application/json'})
-
- if integration:
- assert response.status_code == 200
- assert Issue.objects.filter(status='closed').count() == 0
- else:
- assert response.status_code == 404
- assert Issue.objects.filter(status='closed').count() == 0
-
-
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('integration_id', integrations)
-def test_integration_webhook_post_no_secret(db, client, project_id, integration_id):
- url = reverse('integration_webhook', args=[project_id, integration_id])
- response = client.post(url, {})
-
- assert response.status_code == 404
- assert Issue.objects.filter(status='closed').count() == 0
diff --git a/rdmo/projects/tests/test_view_issue.py b/rdmo/projects/tests/test_view_issue.py
deleted file mode 100644
index cf4f6d745e..0000000000
--- a/rdmo/projects/tests/test_view_issue.py
+++ /dev/null
@@ -1,226 +0,0 @@
-from unittest.mock import Mock
-
-import pytest
-
-from django.core import mail
-from django.http import HttpResponseRedirect
-from django.urls import reverse
-
-from rdmo.core.constants import VALUE_TYPE_FILE
-
-from ..models import Issue, Project
-
-users = (
- ('owner', 'owner'),
- ('manager', 'manager'),
- ('author', 'author'),
- ('guest', 'guest'),
- ('user', 'user'),
- ('site', 'site'),
- ('anonymous', None),
-)
-
-view_issue_permission_map = {
- 'owner': [1, 2, 3, 4, 12],
- 'manager': [1, 3, 5, 12],
- 'author': [1, 3, 5, 12],
- 'guest': [1, 3, 5, 12],
- 'user': [12],
- 'api': [1, 2, 3, 4, 5, 12],
- 'site': [1, 2, 3, 4, 5, 12]
-}
-
-change_issue_permission_map = delete_issue_permission_map = {
- 'owner': [1, 2, 3, 4, 12],
- 'manager': [1, 3],
- 'author': [1, 3],
- 'api': [1, 2, 3, 4, 12],
- 'site': [1, 2, 3, 4, 12],
-}
-
-issues = [1, 2, 3, 4, 9]
-
-integration_pk = 1
-
-issue_status = ('open', 'in_progress', 'closed')
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('issue_id', issues)
-def test_issue(db, client, username, password, issue_id):
- client.login(username=username, password=password)
- issue = Issue.objects.get(id=issue_id)
-
- url = reverse('issue', args=[issue.project_id, issue_id])
- response = client.get(url)
-
- if issue.project_id in view_issue_permission_map.get(username, []):
- assert response.status_code == 200
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('issue_id', issues)
-def test_issue_update_get(db, client, username, password, issue_id):
- client.login(username=username, password=password)
- issue = Issue.objects.get(id=issue_id)
-
- url = reverse('issue_update', args=[issue.project_id, issue_id])
- response = client.get(url)
-
- if issue.project_id in change_issue_permission_map.get(username, []):
- assert response.status_code == 200
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('issue_id', issues)
-@pytest.mark.parametrize('status', issue_status)
-def test_issue_update_post(db, client, username, password, issue_id, status):
- client.login(username=username, password=password)
- issue = Issue.objects.get(id=issue_id)
-
- url = reverse('issue_update', args=[issue.project_id, issue_id])
- data = {
- 'status': status
- }
- response = client.post(url, data)
-
- if issue.project_id in change_issue_permission_map.get(username, []):
- assert response.status_code == 302
- assert Issue.objects.get(id=issue_id).status == status
- else:
- if password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
- assert Issue.objects.get(id=issue_id).status == issue.status
-
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('issue_id', issues)
-def test_issue_send_get(db, client, username, password, issue_id):
- client.login(username=username, password=password)
- issue = Issue.objects.get(id=issue_id)
-
- url = reverse('issue_update', args=[issue.project_id, issue_id])
- response = client.get(url)
-
- if issue.project_id in change_issue_permission_map.get(username, []):
- assert response.status_code == 200
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('issue_id', issues)
-def test_issue_send_post_email(db, client, username, password, issue_id):
- client.login(username=username, password=password)
- issue = Issue.objects.get(id=issue_id)
-
- url = reverse('issue_send', args=[issue.project_id, issue_id])
- data = {
- 'subject': 'Subject',
- 'message': 'Message',
- 'recipients': ['email@example.com']
- }
- response = client.post(url, data)
-
- if issue.project_id in change_issue_permission_map.get(username, []):
- assert response.status_code == 302
- assert len(mail.outbox) == 1
- assert mail.outbox[0].subject == '[example.com] Subject'
- assert mail.outbox[0].body == 'Message'
- else:
- if password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
- assert len(mail.outbox) == 0
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('issue_id', issues)
-def test_issue_send_post_attachments(db, client, files, username, password, issue_id):
- client.login(username=username, password=password)
- issue = Issue.objects.get(id=issue_id)
-
- view = issue.project.views.first()
- file = issue.project.values.filter(snapshot=None, value_type=VALUE_TYPE_FILE).first()
-
- if file and view:
- url = reverse('issue_send', args=[issue.project_id, issue_id])
- data = {
- 'subject': 'Subject',
- 'message': 'Message',
- 'recipients': 'email@example.com',
- 'attachments_answers': 'project_answers',
- 'attachments_views': str(view.id),
- 'attachments_files': str(file.id),
- 'attachments_snapshot': '',
- 'attachments_format': 'html'
- }
- response = client.post(url, data)
-
- if issue.project_id in change_issue_permission_map.get(username, []):
- assert response.status_code == 302
- assert len(mail.outbox) == 1
- assert mail.outbox[0].subject == '[example.com] Subject'
- assert mail.outbox[0].body == 'Message'
-
- attachments = mail.outbox[0].attachments
- assert len(attachments) == 3
- assert attachments[0][0] == 'Test.html'
- assert attachments[0][2] == 'text/html; charset=utf-8'
- assert attachments[1][0] == 'Test.html'
- assert attachments[1][2] == 'text/html; charset=utf-8'
- assert attachments[2][0] == 'test.txt'
- assert attachments[2][2] == 'text/plain'
- else:
- if password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
- assert len(mail.outbox) == 0
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('issue_id', issues)
-def test_issue_send_post_integration(db, client, mocker, username, password, issue_id):
- mocked_send_issue = Mock(return_value=HttpResponseRedirect(redirect_to='https://example.com/login/oauth/authorize'))
- mocker.patch('rdmo.projects.providers.SimpleIssueProvider.send_issue', mocked_send_issue)
-
- client.login(username=username, password=password)
- issue = Issue.objects.get(id=issue_id)
-
- url = reverse('issue_send', args=[issue.project_id, issue_id])
- data = {
- 'subject': 'Subject',
- 'message': 'Message',
- 'integration': [integration_pk]
- }
- response = client.post(url, data)
-
- if issue.project_id in change_issue_permission_map.get(username, []):
- if integration_pk in Project.objects.get(pk=issue.project_id).integrations.values_list('id', flat=True):
- assert response.status_code == 302
- assert response.url.startswith('https://example.com')
- else:
- assert response.status_code == 200
- else:
- if password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
- assert not response.url.startswith('https://example.com')
diff --git a/rdmo/projects/tests/test_view_membership.py b/rdmo/projects/tests/test_view_membership.py
deleted file mode 100644
index b8cc5e87d5..0000000000
--- a/rdmo/projects/tests/test_view_membership.py
+++ /dev/null
@@ -1,301 +0,0 @@
-import pytest
-
-from django.core import mail
-from django.urls import reverse
-
-from rdmo.projects.models import Invite, Membership
-
-users = (
- ('owner', 'owner'),
- ('manager', 'manager'),
- ('author', 'author'),
- ('guest', 'guest'),
- ('user', 'user'),
- ('site', 'site'),
- ('anonymous', None),
-)
-
-add_membership_permission_map = {
- 'api': [1, 2, 3, 4, 5],
- 'site': [1, 2, 3, 4, 5]
-}
-
-change_membership_permission_map = delete_membership_permission_map = {
- 'owner': [1, 2, 3, 4, 5],
- 'api': [1, 2, 3, 4, 5],
- 'site': [1, 2, 3, 4, 5]
-}
-
-projects = [1, 2, 3, 4, 5]
-memberships = [1, 2, 3, 4]
-
-membership_roles = ('owner', 'manager', 'author', 'guest')
-
-excluded_invite_ids = [1, 2]
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-def test_membership_create_get(db, client, username, password, project_id):
- client.login(username=username, password=password)
-
- url = reverse('membership_create', args=[project_id])
- response = client.get(url)
-
- if project_id in add_membership_permission_map.get(username, []):
- assert response.status_code == 200
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
-
-@pytest.mark.parametrize('PROJECT_SEND_INVITE', [False, True])
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('membership_role', membership_roles)
-def test_membership_create_post(db, client, settings,
- username, password, project_id, membership_role, PROJECT_SEND_INVITE):
- settings.PROJECT_SEND_INVITE = PROJECT_SEND_INVITE
- client.login(username=username, password=password)
-
- url = reverse('membership_create', args=[project_id])
- data = {
- 'username_or_email': 'user',
- 'role': membership_role
- }
- response = client.post(url, data)
-
- if project_id in add_membership_permission_map.get(username, []):
- assert response.status_code == 302
- assert Invite.objects.get(project_id=project_id, user__username='user',
- email='user@example.com', role=membership_role)
- assert not Membership.objects.filter(project_id=project_id,
- user__username='user', role=membership_role).exists()
- assert len(mail.outbox) == int(PROJECT_SEND_INVITE)
- else:
- if password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
- assert not Invite.objects.exclude(id__in=excluded_invite_ids).exists()
- assert len(mail.outbox) == 0
-
-
-@pytest.mark.parametrize('PROJECT_SEND_INVITE', [False, True])
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('membership_role', membership_roles)
-def test_membership_create_post_mail(db, client, settings,
- username, password, project_id, membership_role, PROJECT_SEND_INVITE):
- settings.PROJECT_SEND_INVITE = PROJECT_SEND_INVITE
- client.login(username=username, password=password)
-
- url = reverse('membership_create', args=[project_id])
- data = {
- 'username_or_email': 'someuser@example.com',
- 'role': membership_role
- }
- response = client.post(url, data)
-
- if project_id in add_membership_permission_map.get(username, []):
- if not PROJECT_SEND_INVITE:
- assert response.status_code == 200
- assert not Invite.objects.filter(project_id=project_id, user=None,
- email='someuser@example.com', role=membership_role)
- else:
- assert response.status_code == 302
- assert Invite.objects.get(project_id=project_id, user=None,
- email='someuser@example.com', role=membership_role)
- assert len(mail.outbox) == int(PROJECT_SEND_INVITE)
- else:
- if password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
- assert not Invite.objects.exclude(id__in=excluded_invite_ids).exists()
- assert len(mail.outbox) == 0
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('membership_role', membership_roles)
-def test_membership_create_post_error(db, client, username, password, membership_role):
- client.login(username=username, password=password)
-
- project_id = 1
- url = reverse('membership_create', args=[project_id])
- data = {
- 'username_or_email': 'guest',
- 'role': membership_role
- }
- response = client.post(url, data)
-
- assert not Invite.objects.exclude(id__in=excluded_invite_ids).exists()
- assert len(mail.outbox) == 0
-
- if project_id in add_membership_permission_map.get(username, []):
- assert response.status_code == 200
- else:
- if password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('membership_role', membership_roles)
-def test_membership_create_post_mail_error(db, client, username, password, membership_role):
- client.login(username=username, password=password)
-
- project_id = 1
- url = reverse('membership_create', args=[project_id])
- data = {
- 'username_or_email': 'guest@example.com',
- 'role': membership_role
- }
- response = client.post(url, data)
-
- assert not Invite.objects.exclude(id__in=excluded_invite_ids).exists()
- assert len(mail.outbox) == 0
-
- if project_id in add_membership_permission_map.get(username, []):
- assert response.status_code == 200
- else:
- if password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('membership_role', membership_roles)
-def test_membership_create_post_silent(db, client, username, password, membership_role):
- client.login(username=username, password=password)
-
- project_id = 1
- url = reverse('membership_create', args=[project_id])
- data = {
- 'username_or_email': 'user',
- 'role': membership_role,
- 'silent': True
- }
- response = client.post(url, data)
-
- if project_id in add_membership_permission_map.get(username, []):
- assert response.status_code == 302
-
- if username == 'site':
- assert not Invite.objects.exclude(id__in=excluded_invite_ids).exists()
- assert Membership.objects.get(project_id=project_id, user__username='user', role=membership_role)
- assert len(mail.outbox) == 0
- else:
- assert Invite.objects.get(project_id=project_id, user__username='user',
- email='user@example.com', role=membership_role)
- assert not Membership.objects.filter(project_id=project_id, user__username='user',
- role=membership_role).exists()
- assert len(mail.outbox) == 1
-
- else:
- if password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('membership_id', memberships)
-def test_membership_update_get(db, client, username, password, project_id, membership_id):
- client.login(username=username, password=password)
- membership = Membership.objects.filter(project_id=project_id, id=membership_id).first()
-
- url = reverse('membership_update', args=[project_id, membership_id])
- response = client.get(url)
-
- if membership:
- if project_id in change_membership_permission_map.get(username, []):
- assert response.status_code == 200
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
- else:
- assert response.status_code == 404
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('membership_id', memberships)
-@pytest.mark.parametrize('membership_role', membership_roles)
-def test_membership_update_post(db, client, username, password, project_id, membership_id, membership_role):
- client.login(username=username, password=password)
- membership = Membership.objects.filter(project_id=project_id, id=membership_id).first()
-
- url = reverse('membership_update', args=[project_id, membership_id])
- data = {
- 'role': membership_role
- }
- response = client.post(url, data)
-
- if membership:
- if project_id in change_membership_permission_map.get(username, []):
- assert response.status_code == 302
- assert Membership.objects.get(project_id=project_id, id=membership_id).role == membership_role
-
- else:
- if password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
- assert Membership.objects.get(project_id=project_id, id=membership_id).role == membership.role
- else:
- assert response.status_code == 404
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('membership_id', memberships)
-def test_membership_delete_get(db, client, username, password, project_id, membership_id):
- client.login(username=username, password=password)
- membership = Membership.objects.filter(project_id=project_id, id=membership_id).first()
-
- url = reverse('membership_delete', args=[project_id, membership_id])
- response = client.get(url)
-
- if membership:
- if project_id in delete_membership_permission_map.get(username, []):
- assert response.status_code == 200
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
- else:
- assert response.status_code == 404
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('membership_id', memberships)
-def test_membership_delete_post(db, client, mocker, username, password, project_id, membership_id):
- client.login(username=username, password=password)
- membership = Membership.objects.filter(project_id=project_id, id=membership_id).first()
-
- url = reverse('membership_delete', args=[project_id, membership_id])
- response = client.post(url)
-
- if membership:
- if project_id in delete_membership_permission_map.get(username, []):
- if membership.user.username == 'owner':
- assert response.status_code == 400
- else:
- assert response.status_code == 302
- assert not Membership.objects.filter(project_id=project_id, id=membership_id).first()
- elif password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
- else:
- assert response.status_code == 404
diff --git a/rdmo/projects/tests/test_view_membership_multisite.py b/rdmo/projects/tests/test_view_membership_multisite.py
deleted file mode 100644
index 603fe07afb..0000000000
--- a/rdmo/projects/tests/test_view_membership_multisite.py
+++ /dev/null
@@ -1,106 +0,0 @@
-import pytest
-
-from django.contrib.auth import get_user_model
-from django.contrib.sites.models import Site
-from django.core import mail
-from django.urls import reverse
-
-from ..models import Invite, Project
-from ..utils import get_invite_email_project_path
-
-users = (
- ('owner', 'owner'),
- ('manager', 'manager'),
- ('author', 'author'),
- ('guest', 'guest'),
- ('user', 'user'),
- ('site', 'site'),
- ('anonymous', None),
-)
-
-add_membership_permission_map = {
- 'api': [1, 2, 3, 4, 5],
- 'site': [1, 2, 3, 4, 5]
-}
-
-projects = [1, 2, 3, 4, 5]
-memberships = [1, 2, 3, 4]
-
-membership_roles = ('owner', 'manager', 'author', 'guest')
-
-sites_domains = ('example.com', 'foo.com', 'bar.com')
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('membership_role', membership_roles)
-@pytest.mark.parametrize('site_domain', sites_domains)
-def test_get_invite_email_project_path_function(db, client, settings, username, password, project_id,
- membership_role, site_domain):
- settings.MULTISITE = True
-
- client.login(username=username, password=password)
-
- current_site = Site.objects.get_current()
- foo_site, _ = Site.objects.get_or_create(domain=site_domain, name=site_domain)
- foo_username = f'{site_domain}-test-user'
- foo_email = f'{foo_username}@{site_domain}'
- foo_user, _ = get_user_model().objects.get_or_create(username=foo_username, email=foo_email,
- password=foo_username)
- foo_user.role.member.set([foo_site])
- project = Project.objects.get(pk=project_id)
-
- invite = Invite(project=project, user=foo_user, role=membership_role)
- invite.make_token()
- invite.save()
-
- invite_email_project_path = get_invite_email_project_path(invite)
- if current_site.domain == site_domain:
- assert invite_email_project_path.startswith('/projects')
- else:
- assert invite_email_project_path.startswith('http://' + site_domain + '/projects')
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-@pytest.mark.parametrize('membership_role', membership_roles)
-@pytest.mark.parametrize('site_domain', sites_domains)
-def test_invite_email_project_path_email_body(db, client, settings, username, password, project_id,
- membership_role, site_domain):
- settings.MULTISITE = True
-
- client.login(username=username, password=password)
-
- current_site = Site.objects.get_current()
- foo_site, _ = Site.objects.get_or_create(domain=site_domain, name=site_domain)
- foo_username = f'{site_domain}-user'
- foo_email = f'{foo_username}@{site_domain}'
- foo_user, _ = get_user_model().objects.get_or_create(username=f'{site_domain}-user', email=foo_email,
- password=foo_username)
- foo_user.role.member.set([foo_site])
- project = Project.objects.get(pk=project_id)
-
- url = reverse('membership_create', args=[project_id])
- data = {
- 'username_or_email': foo_email,
- 'role': membership_role
- }
- response = client.post(url, data)
-
- invite = Invite(project=project, user=foo_user, role=membership_role)
- invite.make_token()
- invite.save()
-
- if project_id in add_membership_permission_map.get(username, []):
- if current_site.domain == site_domain:
- assert 'http://testserver/' in mail.outbox[0].body
- else:
- assert f'http://{foo_site.domain}/' in mail.outbox[0].body
-
- assert response.status_code == 302
- assert len(mail.outbox) == 1
- else:
- if password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
- assert len(mail.outbox) == 0
diff --git a/rdmo/projects/tests/test_view_project.py b/rdmo/projects/tests/test_view_project.py
deleted file mode 100644
index 5cdabb181e..0000000000
--- a/rdmo/projects/tests/test_view_project.py
+++ /dev/null
@@ -1,896 +0,0 @@
-import re
-
-import pytest
-
-# from django.contrib.auth.models import Group, User
-# from django.urls import resolve
-from django.urls import reverse
-
-# from rdmo.questions.models import Catalog
-# from rdmo.tasks.models import Task
-# from rdmo.views.models import View
-
-# from ..forms import CatalogChoiceField
-# from ..models import Project
-
-users = (
- ('owner', 'owner'),
- ('manager', 'manager'),
- ('author', 'author'),
- ('guest', 'guest'),
- ('user', 'user'),
- ('editor', 'editor'),
- ('reviewer', 'reviewer'),
- ('api', 'api'),
- ('site', 'site'),
- ('anonymous', None)
-)
-
-view_project_permission_map = {
- 'owner': [1, 2, 3, 4, 5, 10, 12],
- 'manager': [1, 3, 5, 7, 12],
- 'author': [1, 3, 5, 8, 12],
- 'guest': [1, 3, 5, 9, 12],
- 'user': [12],
- 'editor': [12],
- 'reviewer': [12],
- 'api': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
- 'site': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
-}
-
-change_project_permission_map = {
- 'owner': [1, 2, 3, 4, 5, 10, 12],
- 'manager': [1, 3, 5, 7],
- 'api': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
- 'site': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
-}
-
-delete_project_permission_map = {
- 'owner': [1, 2, 3, 4, 5, 10, 12],
- 'api': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
- 'site': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
-}
-
-export_project_permission_map = {
- 'owner': [1, 2, 3, 4, 5, 10, 12],
- 'manager': [1, 3, 5, 7],
- 'api': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
- 'site': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
-}
-
-projects = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
-
-export_formats = ('html', )
-
-site_id = 1
-project_id = 1
-parent_id = 3
-parent_ancestors = [2, 3]
-catalog_id = 1
-view_id = 1
-task_id = 1
-
-@pytest.mark.parametrize('username,password', users)
-def test_list(db, client, username, password):
- client.login(username=username, password=password)
-
- url = reverse('projects')
- response = client.get(url)
-
- projects = re.findall(r'/projects/(\d+)/', response.content.decode())
-
- if password:
- assert response.status_code == 200
- # assertTemplateUsed(response, 'projects/projects.html')
-
- if username in ('site', 'api'):
- assert projects == []
- # assert response.context['number_of_projects'] == len([])
- # assertContains(response, 'View all projects on')
- else:
- # user_projects_map = view_project_permission_map.get(username, [])
- assert sorted(set(map(int, projects))) == []
- # assert response.context['number_of_projects'] == len(user_projects_map)
- # assertNotContains(response, 'View all projects on')
- else:
- assert response.status_code == 302
-
-
-@pytest.mark.parametrize('username,password', users)
-@pytest.mark.parametrize('project_id', projects)
-def test_detail(db, client, username, password, project_id):
- client.login(username=username, password=password)
-
- url = reverse('project', args=[project_id])
- response = client.get(url)
-
- if project_id in view_project_permission_map.get(username, []):
- assert response.status_code == 200
- else:
- if password:
- assert response.status_code == 403
- else:
- assert response.status_code == 302
-
-
-# @pytest.mark.parametrize('username,password', users)
-# def test_project_create_get(db, client, username, password):
-# client.login(username=username, password=password)
-
-# url = reverse('project_create')
-# response = client.get(url)
-
-# if password:
-# assert response.status_code == 200
-
-# # check the parent select dropdown
-# for project_id in re.findall(r'
-
- {% trans "You will be redirected shortly." %}
-
-
-
-
{% endblock%}
diff --git a/rdmo/projects/templates/projects/project_interview.html b/rdmo/projects/templates/projects/project_interview.html
index 7e94ea0096..ebb548a062 100644
--- a/rdmo/projects/templates/projects/project_interview.html
+++ b/rdmo/projects/templates/projects/project_interview.html
@@ -1,7 +1,5 @@
-{% extends 'core/page.html' %}
+{% extends 'core/base.html' %}
{% load static %}
-{% load i18n %}
-{% load core_tags %}
{% block head %}
@@ -18,13 +16,7 @@
{% endblock %}
-{% block sidebar %}
-
-
-
-{% endblock %}
-
-{% block page %}
+{% block content %}
diff --git a/rdmo/projects/templates/projects/projects.html b/rdmo/projects/templates/projects/projects.html
index b8fa1eecdb..ad58f7a37a 100644
--- a/rdmo/projects/templates/projects/projects.html
+++ b/rdmo/projects/templates/projects/projects.html
@@ -1,20 +1,17 @@
-{% extends 'core/bs53/base.html' %}
+{% extends 'core/base.html' %}
{% load static %}
{% block head %}
-
+
{% endblock %}
{% block css %}
-
-
{{ block.super }}
{% endblock %}
{% block js %}
-
-
+ {{ block.super }}
{% endblock %}
diff --git a/webpack.config.js b/webpack.config.js
index 3c18b21eb7..5875727eb7 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -18,17 +18,21 @@ const configList = [
{
name: 'core',
entry: {
- 'bootstrap-bs53': [
- './rdmo/core/assets/js/_bs53/bootstrap.js',
- './rdmo/core/assets/scss/_bs53/bootstrap.scss'
+ 'bootstrap': [
+ './rdmo/core/assets/js/bootstrap.js',
+ './rdmo/core/assets/scss/bootstrap.scss'
],
- 'base-bs53': [
- './rdmo/core/assets/js/_bs53/base.js',
- './rdmo/core/assets/scss/_bs53/base.scss'
+ 'base': [
+ './rdmo/core/assets/js/base.js',
+ './rdmo/core/assets/scss/base.scss'
],
- 'app-bs53': [
- './rdmo/core/assets/js/_bs53/app.js',
- './rdmo/core/assets/scss/_bs53/app.scss'
+ 'home': [
+ './rdmo/core/assets/js/home.js',
+ './rdmo/core/assets/scss/home.scss'
+ ],
+ 'app': [
+ './rdmo/core/assets/js/app.js',
+ './rdmo/core/assets/scss/app.scss'
]
},
output: {
From 4fa628e4decd2640f9eff6e3848acb1c2d23b196 Mon Sep 17 00:00:00 2001
From: Jochen Klar
Date: Fri, 10 Apr 2026 16:43:01 +0200
Subject: [PATCH 16/16] Fix tests
---
rdmo/projects/imports.py | 8 ++++----
rdmo/projects/viewsets.py | 3 +--
2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/rdmo/projects/imports.py b/rdmo/projects/imports.py
index bfb40937cc..7e04f2c218 100644
--- a/rdmo/projects/imports.py
+++ b/rdmo/projects/imports.py
@@ -265,10 +265,10 @@ def submit(self):
response = requests.get(form.cleaned_data['url'])
self.request.session['import_file_name'] = handle_fetched_file(response.content)
- if self.current_project:
- return redirect('project_update_import', self.current_project.id)
- else:
- return redirect('project_create_import')
+ # if self.current_project:
+ # return redirect('project_update_import', self.current_project.id)
+ # else:
+ # return redirect('project_create_import')
return render(self.request, 'projects/project_import_form.html', {
'source_title': 'URL',
diff --git a/rdmo/projects/viewsets.py b/rdmo/projects/viewsets.py
index 5cd2b3f7f4..ec89549474 100644
--- a/rdmo/projects/viewsets.py
+++ b/rdmo/projects/viewsets.py
@@ -631,10 +631,9 @@ def imports(self, request):
'key': key,
'label': label,
'class_name': class_name,
- 'href': reverse('project_create_import', args=[key])
+ # 'href': reverse('project_create_import', args=[key])
} for key, label, class_name in settings.PROJECT_IMPORTS if key in settings.PROJECT_IMPORTS_LIST] )
-
def create(self, request, *args, **kwargs):
response = super().create(request, *args, **kwargs)