* adds EMA tests
* extends compensation tests
* fixes bugs detected by testing
* restructured tests for performance boost
This commit is contained in:
mpeltriaux 2021-11-09 13:06:22 +01:00
parent 9ffd1b4482
commit 81c32d6318
20 changed files with 522 additions and 188 deletions

View File

@ -20,6 +20,8 @@ urlpatterns = [
path('<id>/remove', remove_view, name='acc-remove'), path('<id>/remove', remove_view, name='acc-remove'),
path('<id>/state/new', state_new_view, name='acc-new-state'), path('<id>/state/new', state_new_view, name='acc-new-state'),
path('<id>/action/new', action_new_view, name='acc-new-action'), path('<id>/action/new', action_new_view, name='acc-new-action'),
path('<id>/state/<state_id>/remove', state_remove_view, name='acc-state-remove'),
path('<id>/action/<action_id>/remove', action_remove_view, name='acc-action-remove'),
path('<id>/deadline/new', deadline_new_view, name="acc-new-deadline"), path('<id>/deadline/new', deadline_new_view, name="acc-new-deadline"),
path('<id>/share/<token>', share_view, name='share'), path('<id>/share/<token>', share_view, name='share'),
path('<id>/share', create_share_view, name='share-create'), path('<id>/share', create_share_view, name='share-create'),

View File

@ -20,6 +20,8 @@ urlpatterns = [
path('<id>/remove', remove_view, name='remove'), path('<id>/remove', remove_view, name='remove'),
path('<id>/state/new', state_new_view, name='new-state'), path('<id>/state/new', state_new_view, name='new-state'),
path('<id>/action/new', action_new_view, name='new-action'), path('<id>/action/new', action_new_view, name='new-action'),
path('<id>/state/<state_id>/remove', state_remove_view, name='state-remove'),
path('<id>/action/<action_id>/remove', action_remove_view, name='action-remove'),
path('<id>/deadline/new', deadline_new_view, name="new-deadline"), path('<id>/deadline/new', deadline_new_view, name="new-deadline"),
path('<id>/report', report_view, name='report'), path('<id>/report', report_view, name='report'),
@ -28,10 +30,4 @@ urlpatterns = [
path('document/<doc_id>', get_document_view, name='get-doc'), path('document/<doc_id>', get_document_view, name='get-doc'),
path('document/<doc_id>/remove/', remove_document_view, name='remove-doc'), path('document/<doc_id>/remove/', remove_document_view, name='remove-doc'),
# Generic state routes
path('state/<id>/remove', state_remove_view, name='state-remove'),
# Generic action routes
path('action/<id>/remove', action_remove_view, name='action-remove'),
] ]

View File

@ -50,7 +50,7 @@
<td class="align-middle">{{ action.comment|default_if_none:"" }}</td> <td class="align-middle">{{ action.comment|default_if_none:"" }}</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:action-remove' action.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove action' %}"> <button data-form-url="{% url 'compensation:action-remove' obj.id action.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove action' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

View File

@ -51,7 +51,7 @@
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td> <td class="align-middle">{{ state.surface|floatformat:2 }} m²</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:state-remove' state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}"> <button data-form-url="{% url 'compensation:state-remove' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

View File

@ -51,7 +51,7 @@
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td> <td class="align-middle">{{ state.surface|floatformat:2 }} m²</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:state-remove' state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}"> <button data-form-url="{% url 'compensation:state-remove' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

View File

@ -50,7 +50,7 @@
<td class="align-middle">{{ action.comment|default_if_none:"" }}</td> <td class="align-middle">{{ action.comment|default_if_none:"" }}</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:action-remove' action.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove action' %}"> <button data-form-url="{% url 'compensation:acc-action-remove' obj.id action.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove action' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

View File

@ -51,7 +51,7 @@
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td> <td class="align-middle">{{ state.surface|floatformat:2 }} m²</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:state-remove' state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}"> <button data-form-url="{% url 'compensation:acc-state-remove' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

View File

@ -51,7 +51,7 @@
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td> <td class="align-middle">{{ state.surface|floatformat:2 }} m²</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:state-remove' state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}"> <button data-form-url="{% url 'compensation:acc-state-remove' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

View File

@ -8,60 +8,76 @@ Created on: 27.10.21
from django.urls import reverse from django.urls import reverse
from django.test import Client from django.test import Client
from compensation.models import CompensationState, CompensationAction
from konova.settings import DEFAULT_GROUP from konova.settings import DEFAULT_GROUP
from konova.tests.test_views import BaseViewTestCase from konova.tests.test_views import BaseViewTestCase
class ViewTestCase(BaseViewTestCase): class CompensationViewTestCase(BaseViewTestCase):
"""
These tests focus on proper returned views depending on the user's groups privileges and login status
"""
comp_state = None comp_state = None
comp_action = None comp_action = None
def setUp(self) -> None: @classmethod
super().setUp() def setUpTestData(cls) -> None:
self.create_dummy_states() super().setUpTestData()
self.create_dummy_action() state = cls.create_dummy_states()
cls.compensation.before_states.set([state])
cls.compensation.after_states.set([state])
action = cls.create_dummy_action()
cls.compensation.actions.set([action])
# Prepare urls # Prepare urls
self.index_url = reverse("compensation:index", args=()) cls.index_url = reverse("compensation:index", args=())
self.new_url = reverse("compensation:new", args=(self.intervention.id,)) cls.new_url = reverse("compensation:new", args=(cls.intervention.id,))
self.new_id_url = reverse("compensation:new-id", args=()) cls.new_id_url = reverse("compensation:new-id", args=())
self.detail_url = reverse("compensation:detail", args=(self.compensation.id,)) cls.detail_url = reverse("compensation:detail", args=(cls.compensation.id,))
self.log_url = reverse("compensation:log", args=(self.compensation.id,)) cls.log_url = reverse("compensation:log", args=(cls.compensation.id,))
self.edit_url = reverse("compensation:edit", args=(self.compensation.id,)) cls.edit_url = reverse("compensation:edit", args=(cls.compensation.id,))
self.remove_url = reverse("compensation:remove", args=(self.compensation.id,)) cls.remove_url = reverse("compensation:remove", args=(cls.compensation.id,))
self.report_url = reverse("compensation:report", args=(self.compensation.id,)) cls.report_url = reverse("compensation:report", args=(cls.compensation.id,))
self.state_new_url = reverse("compensation:new-state", args=(self.compensation.id,)) cls.state_new_url = reverse("compensation:new-state", args=(cls.compensation.id,))
self.action_new_url = reverse("compensation:new-action", args=(self.compensation.id,)) cls.action_new_url = reverse("compensation:new-action", args=(cls.compensation.id,))
self.deadline_new_url = reverse("compensation:new-deadline", args=(self.compensation.id,)) cls.deadline_new_url = reverse("compensation:new-deadline", args=(cls.compensation.id,))
self.new_doc_url = reverse("compensation:new-doc", args=(self.compensation.id,)) cls.new_doc_url = reverse("compensation:new-doc", args=(cls.compensation.id,))
self.state_remove_url = reverse("compensation:state-remove", args=(self.comp_state.id,)) cls.state_remove_url = reverse("compensation:state-remove", args=(cls.compensation.id, cls.comp_state.id,))
self.action_remove_url = reverse("compensation:action-remove", args=(self.comp_action.id,)) cls.action_remove_url = reverse("compensation:action-remove", args=(cls.compensation.id, cls.comp_action.id,))
def create_dummy_states(self): def test_anonymous_user(self):
""" Creates an intervention which can be used for tests """ Check correct status code for all requests
Assumption: User not logged in
Returns: Returns:
""" """
self.comp_state = CompensationState.objects.create( client = Client()
surface=10.00,
biotope_type=None,
)
self.compensation.before_states.set([self.comp_state])
self.compensation.after_states.set([self.comp_state])
def create_dummy_action(self): success_urls = [
""" Creates an intervention which can be used for tests self.report_url,
]
fail_urls = [
self.index_url,
self.detail_url,
self.new_url,
self.new_id_url,
self.log_url,
self.edit_url,
self.remove_url,
self.state_new_url,
self.action_new_url,
self.deadline_new_url,
self.state_remove_url,
self.action_remove_url,
self.new_doc_url,
]
Returns: self.assert_url_success(client, success_urls)
self.assert_url_fail(client, fail_urls)
"""
self.comp_action = CompensationAction.objects.create(
amount=10
)
self.compensation.actions.set([self.comp_action])
def test_logged_in_no_groups_shared(self): def test_logged_in_no_groups_shared(self):
""" Check correct status code for all requests """ Check correct status code for all requests
@ -111,6 +127,7 @@ class ViewTestCase(BaseViewTestCase):
client = Client() client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw) client.login(username=self.superuser.username, password=self.superuser_pw)
self.superuser.groups.set([]) self.superuser.groups.set([])
# Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
self.intervention.users.set([]) self.intervention.users.set([])
# Since the user has no groups, it does not matter that data is unshared. There SHOULD not be any difference # Since the user has no groups, it does not matter that data is unshared. There SHOULD not be any difference
@ -140,7 +157,8 @@ class ViewTestCase(BaseViewTestCase):
def test_logged_in_default_group_shared(self): def test_logged_in_default_group_shared(self):
""" Check correct status code for all requests """ Check correct status code for all requests
Assumption: User logged in and has no groups and data is shared Assumption: User logged in, is default group member and data is shared
--> Default group necessary since all base functionalities depend on this group membership
Returns: Returns:
@ -149,6 +167,7 @@ class ViewTestCase(BaseViewTestCase):
client.login(username=self.superuser.username, password=self.superuser_pw) client.login(username=self.superuser.username, password=self.superuser_pw)
group = self.groups.get(name=DEFAULT_GROUP) group = self.groups.get(name=DEFAULT_GROUP)
self.superuser.groups.set([group]) self.superuser.groups.set([group])
# Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
self.intervention.users.set([self.superuser]) self.intervention.users.set([self.superuser])
success_urls = [ success_urls = [
@ -169,34 +188,39 @@ class ViewTestCase(BaseViewTestCase):
] ]
self.assert_url_success(client, success_urls) self.assert_url_success(client, success_urls)
def test_anonymous_user(self): def test_logged_in_default_group_unshared(self):
""" Check correct status code for all requests """ Check correct status code for all requests
Assumption: User not logged in Assumption: User logged in, is default group member and data is NOT shared
--> Default group necessary since all base functionalities depend on this group membership
Returns: Returns:
""" """
client = Client() client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw)
group = self.groups.get(name=DEFAULT_GROUP)
self.superuser.groups.set([group])
# Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
self.intervention.users.set([])
success_urls = [ success_urls = [
self.report_url,
]
fail_urls = [
self.index_url, self.index_url,
self.detail_url, self.detail_url,
self.new_url, self.report_url,
self.new_id_url, self.new_id_url,
self.log_url, ]
fail_urls = [
self.new_url,
self.edit_url, self.edit_url,
self.remove_url,
self.state_new_url, self.state_new_url,
self.action_new_url, self.action_new_url,
self.deadline_new_url, self.deadline_new_url,
self.state_remove_url, self.state_remove_url,
self.action_remove_url, self.action_remove_url,
self.new_doc_url, self.new_doc_url,
self.log_url,
self.remove_url,
] ]
self.assert_url_success(client, success_urls)
self.assert_url_fail(client, fail_urls) self.assert_url_fail(client, fail_urls)
self.assert_url_success(client, success_urls)

View File

@ -110,6 +110,7 @@ def new_id_view(request: HttpRequest):
@login_required @login_required
@default_group_required @default_group_required
@shared_access_required(Compensation, "id")
def edit_view(request: HttpRequest, id: str): def edit_view(request: HttpRequest, id: str):
""" """
Renders a view for editing compensations Renders a view for editing compensations
@ -377,17 +378,19 @@ def deadline_new_view(request: HttpRequest, id: str):
@login_required @login_required
@default_group_required @default_group_required
def state_remove_view(request: HttpRequest, id: str): @shared_access_required(Compensation, "id")
def state_remove_view(request: HttpRequest, id: str, state_id: str):
""" Renders a form for removing a compensation state """ Renders a form for removing a compensation state
Args: Args:
request (HttpRequest): The incoming request request (HttpRequest): The incoming request
id (str): The state's id id (str): The compensation's id
state_id (str): The state's id
Returns: Returns:
""" """
state = get_object_or_404(CompensationState, id=id) state = get_object_or_404(CompensationState, id=state_id)
form = RemoveModalForm(request.POST or None, instance=state, user=request.user) form = RemoveModalForm(request.POST or None, instance=state, user=request.user)
return form.process_request( return form.process_request(
request, request,
@ -397,17 +400,19 @@ def state_remove_view(request: HttpRequest, id: str):
@login_required @login_required
@default_group_required @default_group_required
def action_remove_view(request: HttpRequest, id: str): @shared_access_required(Compensation, "id")
def action_remove_view(request: HttpRequest, id: str, action_id: str):
""" Renders a form for removing a compensation action """ Renders a form for removing a compensation action
Args: Args:
request (HttpRequest): The incoming request request (HttpRequest): The incoming request
id (str): The compensation's id
id (str): The action's id id (str): The action's id
Returns: Returns:
""" """
action = get_object_or_404(CompensationAction, id=id) action = get_object_or_404(CompensationAction, id=action_id)
form = RemoveModalForm(request.POST or None, instance=action, user=request.user) form = RemoveModalForm(request.POST or None, instance=action, user=request.user)
return form.process_request( return form.process_request(
request, request,
@ -415,7 +420,7 @@ def action_remove_view(request: HttpRequest, id: str):
) )
def report_view(request:HttpRequest, id: str): def report_view(request: HttpRequest, id: str):
""" Renders the public report view """ Renders the public report view
Args: Args:

View File

@ -16,11 +16,12 @@ from django.shortcuts import render, get_object_or_404, redirect
from compensation.forms.forms import NewEcoAccountForm, EditEcoAccountForm from compensation.forms.forms import NewEcoAccountForm, EditEcoAccountForm
from compensation.forms.modalForms import NewStateModalForm, NewActionModalForm, NewDeadlineModalForm from compensation.forms.modalForms import NewStateModalForm, NewActionModalForm, NewDeadlineModalForm
from compensation.models import EcoAccount, EcoAccountDocument from compensation.models import EcoAccount, EcoAccountDocument, CompensationState, CompensationAction
from compensation.tables import EcoAccountTable from compensation.tables import EcoAccountTable
from intervention.forms.modalForms import NewDeductionModalForm, ShareInterventionModalForm from intervention.forms.modalForms import NewDeductionModalForm, ShareInterventionModalForm
from konova.contexts import BaseContext from konova.contexts import BaseContext
from konova.decorators import any_group_check, default_group_required, conservation_office_group_required from konova.decorators import any_group_check, default_group_required, conservation_office_group_required, \
shared_access_required
from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm, RecordModalForm from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm, RecordModalForm
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.utils.documents import get_document, remove_document from konova.utils.documents import get_document, remove_document
@ -99,6 +100,7 @@ def new_view(request: HttpRequest):
@login_required @login_required
@default_group_required
def new_id_view(request: HttpRequest): def new_id_view(request: HttpRequest):
""" JSON endpoint """ JSON endpoint
@ -353,6 +355,50 @@ def action_new_view(request: HttpRequest, id: str):
) )
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def state_remove_view(request: HttpRequest, id: str, state_id: str):
""" Renders a form for removing a compensation state
Args:
request (HttpRequest): The incoming request
id (str): The compensation's id
state_id (str): The state's id
Returns:
"""
state = get_object_or_404(CompensationState, id=state_id)
form = RemoveModalForm(request.POST or None, instance=state, user=request.user)
return form.process_request(
request,
msg_success=_("State removed")
)
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def action_remove_view(request: HttpRequest, id: str, action_id: str):
""" Renders a form for removing a compensation action
Args:
request (HttpRequest): The incoming request
id (str): The compensation's id
id (str): The action's id
Returns:
"""
action = get_object_or_404(CompensationAction, id=action_id)
form = RemoveModalForm(request.POST or None, instance=action, user=request.user)
return form.process_request(
request,
msg_success=_("Action removed")
)
@login_required @login_required
def deadline_new_view(request: HttpRequest, id: str): def deadline_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new states for an eco account """ Renders a form for adding new states for an eco account

View File

@ -48,7 +48,7 @@
<td class="align-middle">{{ action.comment|default_if_none:"" }}</td> <td class="align-middle">{{ action.comment|default_if_none:"" }}</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'ema:action-remove' action.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove action' %}"> <button data-form-url="{% url 'ema:action-remove' obj.id action.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove action' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

View File

@ -49,7 +49,7 @@
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td> <td class="align-middle">{{ state.surface|floatformat:2 }} m²</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'ema:state-remove' state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}"> <button data-form-url="{% url 'ema:state-remove' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

View File

@ -49,7 +49,7 @@
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td> <td class="align-middle">{{ state.surface|floatformat:2 }} m²</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'ema:state-remove' state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}"> <button data-form-url="{% url 'ema:state-remove' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

7
ema/tests/__init__.py Normal file
View File

@ -0,0 +1,7 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 26.10.21
"""

200
ema/tests/test_views.py Normal file
View File

@ -0,0 +1,200 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 26.10.21
"""
from django.db.models import Q
from django.urls import reverse
from django.test.client import Client
from compensation.tests.test_views import CompensationViewTestCase
from ema.models import Ema
from intervention.models import ResponsibilityData
from konova.models import Geometry
from konova.settings import DEFAULT_GROUP, ETS_GROUP
from user.models import UserActionLogEntry, UserAction
class EmaViewTestCase(CompensationViewTestCase):
""" Test cases for EMA.
Since we inherit most tests functions from CompensationViewTestCase, we only need to add some EMA specific
test functions
"""
ema = None
@classmethod
def setUpTestData(cls) -> None:
super().setUpTestData()
# Create dummy data and related objects, like states or actions
cls.create_dummy_data()
state = cls.create_dummy_states()
action = cls.create_dummy_action()
cls.ema.before_states.set([state])
cls.ema.after_states.set([state])
cls.ema.actions.set([action])
# Prepare urls
cls.index_url = reverse("ema:index", args=())
cls.new_url = reverse("ema:new", args=())
cls.new_id_url = reverse("ema:new-id", args=())
cls.detail_url = reverse("ema:detail", args=(cls.ema.id,))
cls.log_url = reverse("ema:log", args=(cls.ema.id,))
cls.edit_url = reverse("ema:edit", args=(cls.ema.id,))
cls.remove_url = reverse("ema:remove", args=(cls.ema.id,))
cls.share_url = reverse("ema:share", args=(cls.ema.id, cls.ema.access_token,))
cls.share_create_url = reverse("ema:share-create", args=(cls.ema.id,))
cls.record_url = reverse("ema:record", args=(cls.ema.id,))
cls.report_url = reverse("ema:report", args=(cls.ema.id,))
cls.new_doc_url = reverse("ema:new-doc", args=(cls.ema.id,))
cls.state_new_url = reverse("ema:new-state", args=(cls.ema.id,))
cls.action_new_url = reverse("ema:new-action", args=(cls.ema.id,))
cls.deadline_new_url = reverse("ema:new-deadline", args=(cls.ema.id,))
cls.state_remove_url = reverse("ema:state-remove", args=(cls.ema.id, state.id,))
cls.action_remove_url = reverse("ema:action-remove", args=(cls.ema.id, action.id,))
@classmethod
def create_dummy_data(cls):
# Create dummy data
# Create log entry
action = UserActionLogEntry.objects.create(
user=cls.superuser,
action=UserAction.CREATED,
)
# Create responsible data object
responsibility_data = ResponsibilityData.objects.create()
geometry = Geometry.objects.create()
cls.ema = Ema.objects.create(
identifier="TEST",
title="Test_title",
created=action,
geometry=geometry,
responsible=responsibility_data,
comment="Test",
)
def test_logged_in_default_group_shared(self):
""" Check correct status code for all requests
OVERWRITES DEFAULT COMPENSATION TEST METHOD DUE TO SPECIFIC BEHAVIOUR OF EMAS
Assumption: User logged in, is default group member and data is shared
Normally default group would give access to all base functionalities. In case of EMAs we expect these
requests to fail, since a user must be part of the ets group as well, not only default.
Returns:
"""
client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw)
group = self.groups.get(name=DEFAULT_GROUP)
self.superuser.groups.set([group])
# Sharing does not have any effect in here, since the default group will prohibit further functionality access
# to this user
self.ema.users.set([self.superuser])
success_urls = [
self.index_url,
self.detail_url,
self.report_url,
]
fail_urls = [
self.new_url,
self.new_id_url,
self.edit_url,
self.state_new_url,
self.action_new_url,
self.deadline_new_url,
self.state_remove_url,
self.action_remove_url,
self.new_doc_url,
self.log_url,
self.remove_url,
]
self.assert_url_fail(client, fail_urls)
self.assert_url_success(client, success_urls)
def test_logged_in_ets_group_shared(self):
""" Check correct status code for all requests
Assumption: User logged in, is conservation office group member and data is shared
For EMAs we expect a user to be ETS and default group member to have full access to all functionalities, normally
provided for default group members.
Returns:
"""
client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw)
groups = self.groups.filter(Q(name=ETS_GROUP)|Q(name=DEFAULT_GROUP))
self.superuser.groups.set(groups)
# Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
self.ema.users.set([self.superuser])
success_urls = [
self.index_url,
self.detail_url,
self.report_url,
self.new_url,
self.new_id_url,
self.edit_url,
self.state_new_url,
self.action_new_url,
self.deadline_new_url,
self.state_remove_url,
self.action_remove_url,
self.new_doc_url,
self.log_url,
self.remove_url,
]
self.assert_url_success(client, success_urls)
def test_logged_in_ets_group_unshared(self):
""" Check correct status code for all requests
Assumption: User logged in, is conservation office group member and data is NOT shared
For EMAs we expect a user to be ETS and default group member to have full access to all functionalities, normally
provided for default group members.
Returns:
"""
client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw)
groups = self.groups.filter(Q(name=ETS_GROUP)|Q(name=DEFAULT_GROUP))
self.superuser.groups.set(groups)
# Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
self.ema.users.set([])
success_urls = [
self.index_url,
self.detail_url,
self.report_url,
self.new_url,
self.new_id_url,
]
fail_urls = [
self.edit_url,
self.state_new_url,
self.action_new_url,
self.deadline_new_url,
self.state_remove_url,
self.action_remove_url,
self.new_doc_url,
self.log_url,
self.remove_url,
]
self.assert_url_success(client, success_urls)
self.assert_url_fail(client, fail_urls)
def test_logged_in_default_group_unshared(self):
# overwrite this test, since it's not relevant for EMA but is inherited by the superclass
pass

View File

@ -21,6 +21,8 @@ urlpatterns = [
path('<id>/report', report_view, name='report'), path('<id>/report', report_view, name='report'),
path('<id>/state/new', state_new_view, name='new-state'), path('<id>/state/new', state_new_view, name='new-state'),
path('<id>/action/new', action_new_view, name='new-action'), path('<id>/action/new', action_new_view, name='new-action'),
path('<id>/state/<state_id>/remove', state_remove_view, name='state-remove'),
path('<id>/action/<action_id>/remove', action_remove_view, name='action-remove'),
path('<id>/deadline/new', deadline_new_view, name="new-deadline"), path('<id>/deadline/new', deadline_new_view, name="new-deadline"),
path('<id>/share/<token>', share_view, name='share'), path('<id>/share/<token>', share_view, name='share'),
path('<id>/share', create_share_view, name='share-create'), path('<id>/share', create_share_view, name='share-create'),
@ -31,9 +33,4 @@ urlpatterns = [
path('document/<doc_id>', get_document_view, name='get-doc'), path('document/<doc_id>', get_document_view, name='get-doc'),
path('document/<doc_id>/remove/', remove_document_view, name='remove-doc'), path('document/<doc_id>/remove/', remove_document_view, name='remove-doc'),
# Generic state routes
path('state/<id>/remove', state_remove_view, name='state-remove'),
# Generic action routes
path('action/<id>/remove', action_remove_view, name='action-remove'),
] ]

View File

@ -6,13 +6,13 @@ from django.shortcuts import render, get_object_or_404, redirect
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
import compensation
from compensation.forms.modalForms import NewStateModalForm, NewActionModalForm, NewDeadlineModalForm from compensation.forms.modalForms import NewStateModalForm, NewActionModalForm, NewDeadlineModalForm
from compensation.models import CompensationAction, CompensationState
from ema.forms import NewEmaForm, EditEmaForm from ema.forms import NewEmaForm, EditEmaForm
from ema.tables import EmaTable from ema.tables import EmaTable
from intervention.forms.modalForms import ShareInterventionModalForm from intervention.forms.modalForms import ShareInterventionModalForm
from konova.contexts import BaseContext from konova.contexts import BaseContext
from konova.decorators import conservation_office_group_required, default_group_required from konova.decorators import conservation_office_group_required, shared_access_required
from ema.models import Ema, EmaDocument from ema.models import Ema, EmaDocument
from konova.forms import RemoveModalForm, NewDocumentForm, SimpleGeomForm, RecordModalForm from konova.forms import RemoveModalForm, NewDocumentForm, SimpleGeomForm, RecordModalForm
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
@ -92,6 +92,7 @@ def new_view(request: HttpRequest):
@login_required @login_required
@conservation_office_group_required
def new_id_view(request: HttpRequest): def new_id_view(request: HttpRequest):
""" JSON endpoint """ JSON endpoint
@ -159,6 +160,8 @@ def detail_view(request: HttpRequest, id: str):
@login_required @login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def log_view(request: HttpRequest, id: str): def log_view(request: HttpRequest, id: str):
""" Renders a log view using modal """ Renders a log view using modal
@ -183,6 +186,8 @@ def log_view(request: HttpRequest, id: str):
@login_required @login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def edit_view(request: HttpRequest, id: str): def edit_view(request: HttpRequest, id: str):
""" """
Renders a view for editing compensations Renders a view for editing compensations
@ -219,6 +224,8 @@ def edit_view(request: HttpRequest, id: str):
@login_required @login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def remove_view(request: HttpRequest, id: str): def remove_view(request: HttpRequest, id: str):
""" Renders a modal view for removing the EMA """ Renders a modal view for removing the EMA
@ -239,6 +246,8 @@ def remove_view(request: HttpRequest, id: str):
@login_required @login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def record_view(request: HttpRequest, id: str): def record_view(request: HttpRequest, id: str):
""" Renders a modal view for recording the EMA """ Renders a modal view for recording the EMA
@ -259,6 +268,8 @@ def record_view(request: HttpRequest, id: str):
@login_required @login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def state_new_view(request: HttpRequest, id: str): def state_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new states for an EMA """ Renders a form for adding new states for an EMA
@ -278,6 +289,8 @@ def state_new_view(request: HttpRequest, id: str):
@login_required @login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def action_new_view(request: HttpRequest, id: str): def action_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new actions for an EMA """ Renders a form for adding new actions for an EMA
@ -297,6 +310,8 @@ def action_new_view(request: HttpRequest, id: str):
@login_required @login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def deadline_new_view(request: HttpRequest, id: str): def deadline_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new states for an EMA """ Renders a form for adding new states for an EMA
@ -316,6 +331,8 @@ def deadline_new_view(request: HttpRequest, id: str):
@login_required @login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def document_new_view(request: HttpRequest, id: str): def document_new_view(request: HttpRequest, id: str):
""" Renders a form for uploading new documents """ Renders a form for uploading new documents
@ -334,6 +351,7 @@ def document_new_view(request: HttpRequest, id: str):
@login_required @login_required
@conservation_office_group_required
def get_document_view(request: HttpRequest, doc_id: str): def get_document_view(request: HttpRequest, doc_id: str):
""" Returns the document as downloadable file """ Returns the document as downloadable file
@ -360,6 +378,7 @@ def get_document_view(request: HttpRequest, doc_id: str):
@login_required @login_required
@conservation_office_group_required
def remove_document_view(request: HttpRequest, doc_id: str): def remove_document_view(request: HttpRequest, doc_id: str):
""" Removes the document from the database and file system """ Removes the document from the database and file system
@ -380,37 +399,46 @@ def remove_document_view(request: HttpRequest, doc_id: str):
@login_required @login_required
def state_remove_view(request: HttpRequest, id: str): @conservation_office_group_required
@shared_access_required(Ema, "id")
def state_remove_view(request: HttpRequest, id: str, state_id: str):
""" Renders a form for removing an EMA state """ Renders a form for removing an EMA state
Args: Args:
request (HttpRequest): The incoming request request (HttpRequest): The incoming request
id (str): The state's id id (str): The ema id
state_id (str): The state's id
Returns: Returns:
""" """
return compensation.views.compensation_views.state_remove_view( state = get_object_or_404(CompensationState, id=state_id)
form = RemoveModalForm(request.POST or None, instance=state, user=request.user)
return form.process_request(
request, request,
id msg_success=_("State removed")
) )
@login_required @login_required
def action_remove_view(request: HttpRequest, id: str): @conservation_office_group_required
""" Renders a form for removing an EMA state @shared_access_required(Ema, "id")
def action_remove_view(request: HttpRequest, id: str, action_id: str):
""" Renders a form for removing an EMA action
Args: Args:
request (HttpRequest): The incoming request request (HttpRequest): The incoming request
id (str): The state's id id (str): The ema id
id (str): The action's id
Returns: Returns:
""" """
# Reuses the route logic from compensation view action = get_object_or_404(CompensationAction, id=action_id)
return compensation.views.compensation_views.action_remove_view( form = RemoveModalForm(request.POST or None, instance=action, user=request.user)
return form.process_request(
request, request,
id msg_success=_("Action removed")
) )
@ -505,7 +533,8 @@ def share_view(request: HttpRequest, id: str, token: str):
@login_required @login_required
@default_group_required @conservation_office_group_required
@shared_access_required(Ema, "id")
def create_share_view(request: HttpRequest, id: str): def create_share_view(request: HttpRequest, id: str):
""" Renders sharing form for an Ema """ Renders sharing form for an Ema

View File

@ -10,62 +10,29 @@ from django.test import Client
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.urls import reverse from django.urls import reverse
from intervention.models import Intervention, LegalData, ResponsibilityData
from konova.models import Geometry
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.tests.test_views import BaseViewTestCase from konova.tests.test_views import BaseViewTestCase
from user.models import UserActionLogEntry, UserAction
class ViewTestCase(BaseViewTestCase): class InterventionViewTestCase(BaseViewTestCase):
def setUp(self) -> None:
super().setUp() @classmethod
def setUpTestData(cls) -> None:
super().setUpTestData()
# Prepare urls # Prepare urls
self.index_url = reverse("intervention:index", args=()) cls.index_url = reverse("intervention:index", args=())
self.new_url = reverse("intervention:new", args=()) cls.new_url = reverse("intervention:new", args=())
self.new_id_url = reverse("intervention:new-id", args=()) cls.new_id_url = reverse("intervention:new-id", args=())
self.detail_url = reverse("intervention:detail", args=(self.intervention.id,)) cls.detail_url = reverse("intervention:detail", args=(cls.intervention.id,))
self.log_url = reverse("intervention:log", args=(self.intervention.id,)) cls.log_url = reverse("intervention:log", args=(cls.intervention.id,))
self.edit_url = reverse("intervention:edit", args=(self.intervention.id,)) cls.edit_url = reverse("intervention:edit", args=(cls.intervention.id,))
self.remove_url = reverse("intervention:remove", args=(self.intervention.id,)) cls.remove_url = reverse("intervention:remove", args=(cls.intervention.id,))
self.share_url = reverse("intervention:share", args=(self.intervention.id, self.intervention.access_token,)) cls.share_url = reverse("intervention:share", args=(cls.intervention.id, cls.intervention.access_token,))
self.share_create_url = reverse("intervention:share-create", args=(self.intervention.id,)) cls.share_create_url = reverse("intervention:share-create", args=(cls.intervention.id,))
self.run_check_url = reverse("intervention:run-check", args=(self.intervention.id,)) cls.run_check_url = reverse("intervention:run-check", args=(cls.intervention.id,))
self.record_url = reverse("intervention:record", args=(self.intervention.id,)) cls.record_url = reverse("intervention:record", args=(cls.intervention.id,))
self.report_url = reverse("intervention:report", args=(self.intervention.id,)) cls.report_url = reverse("intervention:report", args=(cls.intervention.id,))
def test_views_logged_in_no_groups(self):
""" Check correct status code for all requests
Assumption: User logged in but has no groups
Returns:
"""
# Login client
client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw)
self.superuser.groups.set([])
success_urls = [
self.index_url,
self.report_url,
self.detail_url,
]
fail_urls = [
self.log_url,
self.new_id_url,
self.new_url,
self.edit_url,
self.remove_url,
self.share_url,
self.share_create_url,
self.run_check_url,
self.record_url,
]
self.assert_url_success(client, success_urls)
self.assert_url_fail(client, fail_urls)
def test_views_anonymous_user(self): def test_views_anonymous_user(self):
""" Check correct status code for all requests """ Check correct status code for all requests
@ -102,6 +69,38 @@ class ViewTestCase(BaseViewTestCase):
response = client.get(url, follow=True) response = client.get(url, follow=True)
self.assertEqual(response.redirect_chain[0], (f"{self.login_url}?next={url}", 302), msg=f"Failed for {url}. Redirect chain is {response.redirect_chain}") self.assertEqual(response.redirect_chain[0], (f"{self.login_url}?next={url}", 302), msg=f"Failed for {url}. Redirect chain is {response.redirect_chain}")
def test_views_logged_in_no_groups(self):
""" Check correct status code for all requests
Assumption: User logged in but has no groups
Returns:
"""
# Login client
client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw)
self.superuser.groups.set([])
success_urls = [
self.index_url,
self.report_url,
self.detail_url,
]
fail_urls = [
self.log_url,
self.new_id_url,
self.new_url,
self.edit_url,
self.remove_url,
self.share_url,
self.share_create_url,
self.run_check_url,
self.record_url,
]
self.assert_url_success(client, success_urls)
self.assert_url_fail(client, fail_urls)
def test_views_logged_in_default_group_shared(self): def test_views_logged_in_default_group_shared(self):
""" Check correct status code for all requests """ Check correct status code for all requests
@ -194,7 +193,7 @@ class ViewTestCase(BaseViewTestCase):
client = Client() client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw) client.login(username=self.superuser.username, password=self.superuser_pw)
# Add user to default group # Add user to zb group
zb_group = self.groups.get(name=ZB_GROUP) zb_group = self.groups.get(name=ZB_GROUP)
self.superuser.groups.set([zb_group]) self.superuser.groups.set([zb_group])
self.intervention.users.set([self.superuser]) self.intervention.users.set([self.superuser])
@ -234,7 +233,7 @@ class ViewTestCase(BaseViewTestCase):
client = Client() client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw) client.login(username=self.superuser.username, password=self.superuser_pw)
# Add user to default group # Add user to zb group
zb_group = self.groups.get(name=ZB_GROUP) zb_group = self.groups.get(name=ZB_GROUP)
self.superuser.groups.set([zb_group]) self.superuser.groups.set([zb_group])
self.intervention.users.set([]) self.intervention.users.set([])
@ -265,7 +264,7 @@ class ViewTestCase(BaseViewTestCase):
def test_views_logged_in_ets_group_shared(self): def test_views_logged_in_ets_group_shared(self):
""" Check correct status code for all requests """ Check correct status code for all requests
Assumption: User logged in and is registration office member and data is shared with Assumption: User logged in and is conservation office member and data is shared with
Returns: Returns:
@ -274,7 +273,7 @@ class ViewTestCase(BaseViewTestCase):
client = Client() client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw) client.login(username=self.superuser.username, password=self.superuser_pw)
# Add user to default group # Add user to ets group
ets_group = Group.objects.get(name=ETS_GROUP) ets_group = Group.objects.get(name=ETS_GROUP)
self.superuser.groups.set([ets_group]) self.superuser.groups.set([ets_group])
self.intervention.users.set([self.superuser]) self.intervention.users.set([self.superuser])

View File

@ -11,7 +11,7 @@ from django.contrib.auth.models import User, Group
from django.test import TestCase, Client from django.test import TestCase, Client
from django.urls import reverse from django.urls import reverse
from compensation.models import Compensation from compensation.models import Compensation, CompensationState, CompensationAction
from intervention.models import LegalData, ResponsibilityData, Intervention from intervention.models import LegalData, ResponsibilityData, Intervention
from konova.management.commands.setup_data import GROUPS_DATA from konova.management.commands.setup_data import GROUPS_DATA
from konova.models import Geometry from konova.models import Geometry
@ -30,33 +30,30 @@ class BaseTestCase(TestCase):
superuser_pw = "root" superuser_pw = "root"
user_pw = "root" user_pw = "root"
@abstractmethod @classmethod
def setUp(self) -> None: def create_users(cls):
# To be implemented in the inheriting classes
raise NotImplementedError
def create_users(self):
# Create superuser and regular user # Create superuser and regular user
self.superuser = User.objects.create_superuser( cls.superuser = User.objects.create_superuser(
username="root", username="root",
email="root@root.com", email="root@root.com",
password=self.superuser_pw, password=cls.superuser_pw,
) )
self.user = User.objects.create_user( cls.user = User.objects.create_user(
username="user1", username="user1",
email="user@root.com", email="user@root.com",
password=self.user_pw password=cls.user_pw
) )
self.users = User.objects.all() cls.users = User.objects.all()
def create_groups(self): @classmethod
def create_groups(cls):
# Create groups # Create groups
for group_data in GROUPS_DATA: for group_data in GROUPS_DATA:
name = group_data.get("name") name = group_data.get("name")
Group.objects.get_or_create( Group.objects.get_or_create(
name=name, name=name,
) )
self.groups = Group.objects.all() cls.groups = Group.objects.all()
class Meta: class Meta:
abstract = True abstract = True
@ -69,13 +66,16 @@ class BaseViewTestCase(BaseTestCase):
login_url = None login_url = None
intervention = None intervention = None
compensation = None compensation = None
comp_state = None
comp_action = None
def setUp(self) -> None: @classmethod
self.create_users() def setUpTestData(cls) -> None:
self.create_groups() cls.create_users()
self.create_dummy_intervention() cls.create_groups()
self.create_dummy_compensation() cls.create_dummy_intervention()
self.login_url = reverse("simple-sso-login") cls.create_dummy_compensation()
cls.login_url = reverse("simple-sso-login")
def assert_url_success(self, client: Client, urls: list): def assert_url_success(self, client: Client, urls: list):
""" Assert for all given urls a direct 200 response """ Assert for all given urls a direct 200 response
@ -122,7 +122,8 @@ class BaseViewTestCase(BaseTestCase):
response = client.get(url) response = client.get(url)
self.assertEqual(response.status_code, 302, msg=f"Failed for {url}") self.assertEqual(response.status_code, 302, msg=f"Failed for {url}")
def create_dummy_intervention(self): @classmethod
def create_dummy_intervention(cls):
""" Creates an intervention which can be used for tests """ Creates an intervention which can be used for tests
Returns: Returns:
@ -131,7 +132,7 @@ class BaseViewTestCase(BaseTestCase):
# Create dummy data # Create dummy data
# Create log entry # Create log entry
action = UserActionLogEntry.objects.create( action = UserActionLogEntry.objects.create(
user=self.superuser, user=cls.superuser,
action=UserAction.CREATED, action=UserAction.CREATED,
) )
# Create legal data object (without M2M laws first) # Create legal data object (without M2M laws first)
@ -140,7 +141,7 @@ class BaseViewTestCase(BaseTestCase):
responsibility_data = ResponsibilityData.objects.create() responsibility_data = ResponsibilityData.objects.create()
geometry = Geometry.objects.create() geometry = Geometry.objects.create()
# Finally create main object, holding the other objects # Finally create main object, holding the other objects
self.intervention = Intervention.objects.create( cls.intervention = Intervention.objects.create(
identifier="TEST", identifier="TEST",
title="Test_title", title="Test_title",
responsible=responsibility_data, responsible=responsibility_data,
@ -149,43 +150,70 @@ class BaseViewTestCase(BaseTestCase):
geometry=geometry, geometry=geometry,
comment="Test", comment="Test",
) )
self.intervention.generate_access_token(make_unique=True) cls.intervention.generate_access_token(make_unique=True)
def create_dummy_compensation(self): @classmethod
def create_dummy_compensation(cls):
""" Creates an intervention which can be used for tests """ Creates an intervention which can be used for tests
Returns: Returns:
""" """
if self.intervention is None: if cls.intervention is None:
self.create_dummy_intervention() cls.create_dummy_intervention()
# Create dummy data # Create dummy data
# Create log entry # Create log entry
action = UserActionLogEntry.objects.create( action = UserActionLogEntry.objects.create(
user=self.superuser, user=cls.superuser,
action=UserAction.CREATED, action=UserAction.CREATED,
) )
geometry = Geometry.objects.create() geometry = Geometry.objects.create()
# Finally create main object, holding the other objects # Finally create main object, holding the other objects
self.compensation = Compensation.objects.create( cls.compensation = Compensation.objects.create(
identifier="TEST", identifier="TEST",
title="Test_title", title="Test_title",
intervention=self.intervention, intervention=cls.intervention,
created=action, created=action,
geometry=geometry, geometry=geometry,
comment="Test", comment="Test",
) )
self.intervention.generate_access_token(make_unique=True) cls.intervention.generate_access_token(make_unique=True)
@classmethod
def create_dummy_states(cls):
""" Creates an intervention which can be used for tests
Returns:
"""
cls.comp_state = CompensationState.objects.create(
surface=10.00,
biotope_type=None,
)
return cls.comp_state
@classmethod
def create_dummy_action(cls):
""" Creates an intervention which can be used for tests
Returns:
"""
cls.comp_action = CompensationAction.objects.create(
amount=10
)
return cls.comp_action
class KonovaViewTestCase(BaseViewTestCase): class KonovaViewTestCase(BaseViewTestCase):
""" Holds tests for all regular views, which are not app specific """ Holds tests for all regular views, which are not app specific
""" """
def setUp(self) -> None: @classmethod
super().setUp() def setUpTestData(cls) -> None:
super().setUpTestData()
self.home_url = reverse("home") cls.home_url = reverse("home")
def test_views_logged_in_no_groups(self): def test_views_logged_in_no_groups(self):
""" Check correct status code for all requests """ Check correct status code for all requests
@ -221,17 +249,18 @@ class KonovaViewTestCase(BaseViewTestCase):
class AutocompleteTestCase(BaseViewTestCase): class AutocompleteTestCase(BaseViewTestCase):
def setUp(self) -> None: @classmethod
super().setUp() def setUpTestData(cls) -> None:
self.atcmplt_accs = reverse("accounts-autocomplete") super().setUpTestData()
self.atcmplt_interventions = reverse("interventions-autocomplete") cls.atcmplt_accs = reverse("accounts-autocomplete")
self.atcmplt_code_comp_action = reverse("codes-compensation-action-autocomplete") cls.atcmplt_interventions = reverse("interventions-autocomplete")
self.atcmplt_code_comp_funding = reverse("codes-compensation-funding-autocomplete") cls.atcmplt_code_comp_action = reverse("codes-compensation-action-autocomplete")
self.atcmplt_code_comp_biotope = reverse("codes-biotope-autocomplete") cls.atcmplt_code_comp_funding = reverse("codes-compensation-funding-autocomplete")
self.atcmplt_code_comp_law = reverse("codes-law-autocomplete") cls.atcmplt_code_comp_biotope = reverse("codes-biotope-autocomplete")
self.atcmplt_code_comp_process = reverse("codes-process-type-autocomplete") cls.atcmplt_code_comp_law = reverse("codes-law-autocomplete")
self.atcmplt_code_comp_reg_off = reverse("codes-registration-office-autocomplete") cls.atcmplt_code_comp_process = reverse("codes-process-type-autocomplete")
self.atcmplt_code_comp_cons_off = reverse("codes-conservation-office-autocomplete") cls.atcmplt_code_comp_reg_off = reverse("codes-registration-office-autocomplete")
cls.atcmplt_code_comp_cons_off = reverse("codes-conservation-office-autocomplete")
def _test_views_anonymous_user(self): def _test_views_anonymous_user(self):
# ATTENTION: As of the current state of django-autocomplete-light, there is no way to check on authenticated # ATTENTION: As of the current state of django-autocomplete-light, there is no way to check on authenticated