Compare commits

...

3 Commits

Author SHA1 Message Date
2957035b5a #19 Tests
* adds EcoAccount tests
* fixes bugs found by testing
2021-11-10 09:11:24 +01:00
0fac17ad68 #19 Tests
* adds EMA test
2021-11-09 15:33:26 +01:00
c221d00c28 #19 Tests
* adds EMA tests
* extends compensation tests
* fixes bugs detected by testing
* restructured tests for performance boost
2021-11-09 13:06:22 +01:00
21 changed files with 819 additions and 197 deletions

View File

@ -20,6 +20,8 @@ urlpatterns = [
path('<id>/remove', remove_view, name='acc-remove'),
path('<id>/state/new', state_new_view, name='acc-new-state'),
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>/share/<token>', share_view, name='share'),
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>/state/new', state_new_view, name='new-state'),
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>/report', report_view, name='report'),
@ -28,10 +30,4 @@ urlpatterns = [
path('document/<doc_id>', get_document_view, name='get-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>
{% 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' %}
</button>
{% endif %}

View File

@ -51,7 +51,7 @@
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td>
<td>
{% 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' %}
</button>
{% endif %}

View File

@ -51,7 +51,7 @@
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td>
<td>
{% 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' %}
</button>
{% endif %}

View File

@ -50,7 +50,7 @@
<td class="align-middle">{{ action.comment|default_if_none:"" }}</td>
<td>
{% 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' %}
</button>
{% endif %}

View File

@ -51,7 +51,7 @@
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td>
<td>
{% 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' %}
</button>
{% endif %}

View File

@ -51,7 +51,7 @@
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td>
<td>
{% 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' %}
</button>
{% endif %}

View File

@ -8,60 +8,74 @@ Created on: 27.10.21
from django.urls import reverse
from django.test import Client
from compensation.models import CompensationState, CompensationAction
from konova.settings import DEFAULT_GROUP
from konova.tests.test_views import BaseViewTestCase
class ViewTestCase(BaseViewTestCase):
comp_state = None
comp_action = None
class CompensationViewTestCase(BaseViewTestCase):
"""
These tests focus on proper returned views depending on the user's groups privileges and login status
def setUp(self) -> None:
super().setUp()
self.create_dummy_states()
self.create_dummy_action()
"""
@classmethod
def setUpTestData(cls) -> None:
super().setUpTestData()
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
self.index_url = reverse("compensation:index", args=())
self.new_url = reverse("compensation:new", args=(self.intervention.id,))
self.new_id_url = reverse("compensation:new-id", args=())
self.detail_url = reverse("compensation:detail", args=(self.compensation.id,))
self.log_url = reverse("compensation:log", args=(self.compensation.id,))
self.edit_url = reverse("compensation:edit", args=(self.compensation.id,))
self.remove_url = reverse("compensation:remove", args=(self.compensation.id,))
self.report_url = reverse("compensation:report", args=(self.compensation.id,))
self.state_new_url = reverse("compensation:new-state", args=(self.compensation.id,))
self.action_new_url = reverse("compensation:new-action", args=(self.compensation.id,))
self.deadline_new_url = reverse("compensation:new-deadline", args=(self.compensation.id,))
self.new_doc_url = reverse("compensation:new-doc", args=(self.compensation.id,))
cls.index_url = reverse("compensation:index", args=())
cls.new_url = reverse("compensation:new", args=(cls.intervention.id,))
cls.new_id_url = reverse("compensation:new-id", args=())
cls.detail_url = reverse("compensation:detail", args=(cls.compensation.id,))
cls.log_url = reverse("compensation:log", args=(cls.compensation.id,))
cls.edit_url = reverse("compensation:edit", args=(cls.compensation.id,))
cls.remove_url = reverse("compensation:remove", args=(cls.compensation.id,))
cls.report_url = reverse("compensation:report", args=(cls.compensation.id,))
cls.state_new_url = reverse("compensation:new-state", args=(cls.compensation.id,))
cls.action_new_url = reverse("compensation:new-action", args=(cls.compensation.id,))
cls.deadline_new_url = reverse("compensation:new-deadline", args=(cls.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,))
self.action_remove_url = reverse("compensation:action-remove", args=(self.comp_action.id,))
cls.state_remove_url = reverse("compensation:state-remove", args=(cls.compensation.id, cls.comp_state.id,))
cls.action_remove_url = reverse("compensation:action-remove", args=(cls.compensation.id, cls.comp_action.id,))
def create_dummy_states(self):
""" Creates an intervention which can be used for tests
def test_anonymous_user(self):
""" Check correct status code for all requests
Assumption: User not logged in
Returns:
"""
self.comp_state = CompensationState.objects.create(
surface=10.00,
biotope_type=None,
)
self.compensation.before_states.set([self.comp_state])
self.compensation.after_states.set([self.comp_state])
client = Client()
def create_dummy_action(self):
""" Creates an intervention which can be used for tests
success_urls = [
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.comp_action = CompensationAction.objects.create(
amount=10
)
self.compensation.actions.set([self.comp_action])
self.assert_url_success(client, success_urls)
self.assert_url_fail(client, fail_urls)
def test_logged_in_no_groups_shared(self):
""" Check correct status code for all requests
@ -111,6 +125,7 @@ class ViewTestCase(BaseViewTestCase):
client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw)
self.superuser.groups.set([])
# Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
self.intervention.users.set([])
# Since the user has no groups, it does not matter that data is unshared. There SHOULD not be any difference
@ -140,7 +155,8 @@ class ViewTestCase(BaseViewTestCase):
def test_logged_in_default_group_shared(self):
""" 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:
@ -149,6 +165,7 @@ class ViewTestCase(BaseViewTestCase):
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([self.superuser])
success_urls = [
@ -169,22 +186,101 @@ class ViewTestCase(BaseViewTestCase):
]
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
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:
"""
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 = [
self.index_url,
self.detail_url,
self.report_url,
self.new_id_url,
]
fail_urls = [
self.new_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)
class EcoAccountViewTestCase(CompensationViewTestCase):
"""
These tests focus on proper returned views depending on the user's groups privileges and login status
EcoAccounts can inherit the same tests used for compensations.
"""
comp_state = None
comp_action = None
@classmethod
def setUpTestData(cls) -> None:
super().setUpTestData()
state = cls.create_dummy_states()
cls.eco_account.before_states.set([state])
cls.eco_account.after_states.set([state])
action = cls.create_dummy_action()
cls.eco_account.actions.set([action])
# Prepare urls
cls.index_url = reverse("compensation:acc-index", args=())
cls.new_url = reverse("compensation:acc-new", args=())
cls.new_id_url = reverse("compensation:acc-new-id", args=())
cls.detail_url = reverse("compensation:acc-detail", args=(cls.eco_account.id,))
cls.log_url = reverse("compensation:acc-log", args=(cls.eco_account.id,))
cls.edit_url = reverse("compensation:acc-edit", args=(cls.eco_account.id,))
cls.remove_url = reverse("compensation:acc-remove", args=(cls.eco_account.id,))
cls.report_url = reverse("compensation:acc-report", args=(cls.eco_account.id,))
cls.state_new_url = reverse("compensation:acc-new-state", args=(cls.eco_account.id,))
cls.action_new_url = reverse("compensation:acc-new-action", args=(cls.eco_account.id,))
cls.deadline_new_url = reverse("compensation:acc-new-deadline", args=(cls.eco_account.id,))
cls.new_doc_url = reverse("compensation:acc-new-doc", args=(cls.eco_account.id,))
cls.state_remove_url = reverse("compensation:acc-state-remove", args=(cls.eco_account.id, cls.comp_state.id,))
cls.action_remove_url = reverse("compensation:acc-action-remove", args=(cls.eco_account.id, cls.comp_action.id,))
def test_logged_in_no_groups_shared(self):
""" Check correct status code for all requests
Assumption: User logged in and has no groups and data is shared
Returns:
"""
client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw)
self.superuser.groups.set([])
self.eco_account.users.set([self.superuser])
# Since the user has no groups, it does not matter that data has been shared. There SHOULD not be any difference
# to a user without access, since the important permissions are missing
success_urls = [
self.index_url,
self.detail_url,
self.report_url,
]
fail_urls = [
self.index_url,
self.detail_url,
self.new_url,
self.new_id_url,
self.log_url,
@ -200,3 +296,111 @@ class ViewTestCase(BaseViewTestCase):
self.assert_url_success(client, success_urls)
self.assert_url_fail(client, fail_urls)
def test_logged_in_no_groups_unshared(self):
""" Check correct status code for all requests
Assumption: User logged in and has no groups and data is shared
Returns:
"""
client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw)
self.superuser.groups.set([])
self.eco_account.users.set([])
# Since the user has no groups, it does not matter that data is unshared. There SHOULD not be any difference
# to a user having shared access, since all important permissions are missing
success_urls = [
self.index_url,
self.detail_url,
self.report_url,
]
fail_urls = [
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,
]
self.assert_url_success(client, success_urls)
self.assert_url_fail(client, fail_urls)
def test_logged_in_default_group_shared(self):
""" Check correct status code for all requests
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:
"""
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.eco_account.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_default_group_unshared(self):
""" Check correct status code for all requests
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:
"""
client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw)
group = self.groups.get(name=DEFAULT_GROUP)
self.superuser.groups.set([group])
self.eco_account.users.set([])
success_urls = [
self.index_url,
self.detail_url,
self.report_url,
self.new_id_url,
self.new_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_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
@default_group_required
@shared_access_required(Compensation, "id")
def edit_view(request: HttpRequest, id: str):
"""
Renders a view for editing compensations
@ -377,17 +378,19 @@ def deadline_new_view(request: HttpRequest, id: str):
@login_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
Args:
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:
"""
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)
return form.process_request(
request,
@ -397,17 +400,19 @@ def state_remove_view(request: HttpRequest, id: str):
@login_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
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=id)
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,

View File

@ -16,16 +16,18 @@ from django.shortcuts import render, get_object_or_404, redirect
from compensation.forms.forms import NewEcoAccountForm, EditEcoAccountForm
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 intervention.forms.modalForms import NewDeductionModalForm, ShareInterventionModalForm
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.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.utils.documents import get_document, remove_document
from konova.utils.generators import generate_qr_code
from konova.utils.message_templates import IDENTIFIER_REPLACED, FORM_INVALID, DATA_UNSHARED, DATA_UNSHARED_EXPLANATION
from konova.utils.message_templates import IDENTIFIER_REPLACED, FORM_INVALID, DATA_UNSHARED, DATA_UNSHARED_EXPLANATION, \
CANCEL_ACC_RECORDED_OR_DEDUCTED
from konova.utils.user_checks import in_group
@ -99,6 +101,7 @@ def new_view(request: HttpRequest):
@login_required
@default_group_required
def new_id_view(request: HttpRequest):
""" JSON endpoint
@ -118,6 +121,7 @@ def new_id_view(request: HttpRequest):
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def edit_view(request: HttpRequest, id: str):
"""
Renders a view for editing compensations
@ -223,6 +227,8 @@ def detail_view(request: HttpRequest, id: str):
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def remove_view(request: HttpRequest, id: str):
""" Renders a modal view for removing the eco account
@ -234,6 +240,15 @@ def remove_view(request: HttpRequest, id: str):
"""
acc = get_object_or_404(EcoAccount, id=id)
# If the eco account has already been recorded OR there are already deductions, it can not be deleted by a regular
# default group user
if acc.recorded is not None or acc.deductions.exists():
user = request.user
if not in_group(user, ETS_GROUP):
messages.info(request, CANCEL_ACC_RECORDED_OR_DEDUCTED)
return redirect("compensation:acc-detail", id=id)
form = RemoveModalForm(request.POST or None, instance=acc, user=request.user)
return form.process_request(
request=request,
@ -244,6 +259,7 @@ def remove_view(request: HttpRequest, id: str):
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def deduction_remove_view(request: HttpRequest, id: str, deduction_id: str):
""" Renders a modal view for removing deductions
@ -270,6 +286,7 @@ def deduction_remove_view(request: HttpRequest, id: str, deduction_id: str):
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def log_view(request: HttpRequest, id: str):
""" Renders a log view using modal
@ -295,6 +312,7 @@ def log_view(request: HttpRequest, id: str):
@login_required
@conservation_office_group_required
@shared_access_required(EcoAccount, "id")
def record_view(request: HttpRequest, id:str):
""" Renders a modal form for recording an eco account
@ -316,6 +334,8 @@ def record_view(request: HttpRequest, id:str):
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def state_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new states for an eco account
@ -335,6 +355,8 @@ def state_new_view(request: HttpRequest, id: str):
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def action_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new actions for an eco account
@ -354,6 +376,52 @@ 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
@default_group_required
@shared_access_required(EcoAccount, "id")
def deadline_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new states for an eco account
@ -373,6 +441,8 @@ def deadline_new_view(request: HttpRequest, id: str):
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def new_document_view(request: HttpRequest, id: str):
""" Renders a form for uploading new documents
@ -391,6 +461,7 @@ def new_document_view(request: HttpRequest, id: str):
@login_required
@default_group_required
def get_document_view(request: HttpRequest, doc_id: str):
""" Returns the document as downloadable file
@ -417,6 +488,8 @@ def get_document_view(request: HttpRequest, doc_id: str):
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def remove_document_view(request: HttpRequest, doc_id: str):
""" Removes the document from the database and file system
@ -438,6 +511,7 @@ def remove_document_view(request: HttpRequest, doc_id: str):
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def new_deduction_view(request: HttpRequest, id: str):
""" Renders a modal form view for creating deductions
@ -555,6 +629,7 @@ def share_view(request: HttpRequest, id: str, token: str):
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def create_share_view(request: HttpRequest, id: str):
""" Renders sharing form for an eco account

View File

@ -48,7 +48,7 @@
<td class="align-middle">{{ action.comment|default_if_none:"" }}</td>
<td>
{% 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' %}
</button>
{% endif %}

View File

@ -49,7 +49,7 @@
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td>
<td>
{% 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' %}
</button>
{% endif %}

View File

@ -49,7 +49,7 @@
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td>
<td>
{% 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' %}
</button>
{% 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
"""

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

@ -0,0 +1,242 @@
"""
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_default_group_unshared(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 NOT 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.
We check on the same tests as in the _shared test, since we want to make sure there is no difference in
between shared and unshared, if the user is only part of the default group.
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([])
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)

View File

@ -21,6 +21,8 @@ urlpatterns = [
path('<id>/report', report_view, name='report'),
path('<id>/state/new', state_new_view, name='new-state'),
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>/share/<token>', share_view, name='share'),
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>/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.utils.translation import gettext_lazy as _
import compensation
from compensation.forms.modalForms import NewStateModalForm, NewActionModalForm, NewDeadlineModalForm
from compensation.models import CompensationAction, CompensationState
from ema.forms import NewEmaForm, EditEmaForm
from ema.tables import EmaTable
from intervention.forms.modalForms import ShareInterventionModalForm
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 konova.forms import RemoveModalForm, NewDocumentForm, SimpleGeomForm, RecordModalForm
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
@ -92,6 +92,7 @@ def new_view(request: HttpRequest):
@login_required
@conservation_office_group_required
def new_id_view(request: HttpRequest):
""" JSON endpoint
@ -159,6 +160,8 @@ def detail_view(request: HttpRequest, id: str):
@login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def log_view(request: HttpRequest, id: str):
""" Renders a log view using modal
@ -183,6 +186,8 @@ def log_view(request: HttpRequest, id: str):
@login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def edit_view(request: HttpRequest, id: str):
"""
Renders a view for editing compensations
@ -219,6 +224,8 @@ def edit_view(request: HttpRequest, id: str):
@login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def remove_view(request: HttpRequest, id: str):
""" Renders a modal view for removing the EMA
@ -239,6 +246,8 @@ def remove_view(request: HttpRequest, id: str):
@login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def record_view(request: HttpRequest, id: str):
""" Renders a modal view for recording the EMA
@ -259,6 +268,8 @@ def record_view(request: HttpRequest, id: str):
@login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def state_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new states for an EMA
@ -278,6 +289,8 @@ def state_new_view(request: HttpRequest, id: str):
@login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def action_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new actions for an EMA
@ -297,6 +310,8 @@ def action_new_view(request: HttpRequest, id: str):
@login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def deadline_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new states for an EMA
@ -316,6 +331,8 @@ def deadline_new_view(request: HttpRequest, id: str):
@login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def document_new_view(request: HttpRequest, id: str):
""" Renders a form for uploading new documents
@ -334,6 +351,7 @@ def document_new_view(request: HttpRequest, id: str):
@login_required
@conservation_office_group_required
def get_document_view(request: HttpRequest, doc_id: str):
""" Returns the document as downloadable file
@ -360,6 +378,7 @@ def get_document_view(request: HttpRequest, doc_id: str):
@login_required
@conservation_office_group_required
def remove_document_view(request: HttpRequest, doc_id: str):
""" Removes the document from the database and file system
@ -380,37 +399,46 @@ def remove_document_view(request: HttpRequest, doc_id: str):
@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
Args:
request (HttpRequest): The incoming request
id (str): The state's id
id (str): The ema id
state_id (str): The state's id
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,
id
msg_success=_("State removed")
)
@login_required
def action_remove_view(request: HttpRequest, id: str):
""" Renders a form for removing an EMA state
@conservation_office_group_required
@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:
request (HttpRequest): The incoming request
id (str): The state's id
id (str): The ema id
id (str): The action's id
Returns:
"""
# Reuses the route logic from compensation view
return compensation.views.compensation_views.action_remove_view(
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,
id
msg_success=_("Action removed")
)
@ -505,7 +533,8 @@ def share_view(request: HttpRequest, id: str, token: str):
@login_required
@default_group_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def create_share_view(request: HttpRequest, id: str):
""" 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.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.tests.test_views import BaseViewTestCase
from user.models import UserActionLogEntry, UserAction
class ViewTestCase(BaseViewTestCase):
def setUp(self) -> None:
super().setUp()
class InterventionViewTestCase(BaseViewTestCase):
@classmethod
def setUpTestData(cls) -> None:
super().setUpTestData()
# Prepare urls
self.index_url = reverse("intervention:index", args=())
self.new_url = reverse("intervention:new", args=())
self.new_id_url = reverse("intervention:new-id", args=())
self.detail_url = reverse("intervention:detail", args=(self.intervention.id,))
self.log_url = reverse("intervention:log", args=(self.intervention.id,))
self.edit_url = reverse("intervention:edit", args=(self.intervention.id,))
self.remove_url = reverse("intervention:remove", args=(self.intervention.id,))
self.share_url = reverse("intervention:share", args=(self.intervention.id, self.intervention.access_token,))
self.share_create_url = reverse("intervention:share-create", args=(self.intervention.id,))
self.run_check_url = reverse("intervention:run-check", args=(self.intervention.id,))
self.record_url = reverse("intervention:record", args=(self.intervention.id,))
self.report_url = reverse("intervention:report", args=(self.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)
cls.index_url = reverse("intervention:index", args=())
cls.new_url = reverse("intervention:new", args=())
cls.new_id_url = reverse("intervention:new-id", args=())
cls.detail_url = reverse("intervention:detail", args=(cls.intervention.id,))
cls.log_url = reverse("intervention:log", args=(cls.intervention.id,))
cls.edit_url = reverse("intervention:edit", args=(cls.intervention.id,))
cls.remove_url = reverse("intervention:remove", args=(cls.intervention.id,))
cls.share_url = reverse("intervention:share", args=(cls.intervention.id, cls.intervention.access_token,))
cls.share_create_url = reverse("intervention:share-create", args=(cls.intervention.id,))
cls.run_check_url = reverse("intervention:run-check", args=(cls.intervention.id,))
cls.record_url = reverse("intervention:record", args=(cls.intervention.id,))
cls.report_url = reverse("intervention:report", args=(cls.intervention.id,))
def test_views_anonymous_user(self):
""" Check correct status code for all requests
@ -102,6 +69,38 @@ class ViewTestCase(BaseViewTestCase):
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}")
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):
""" Check correct status code for all requests
@ -194,7 +193,7 @@ class ViewTestCase(BaseViewTestCase):
client = Client()
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)
self.superuser.groups.set([zb_group])
self.intervention.users.set([self.superuser])
@ -234,7 +233,7 @@ class ViewTestCase(BaseViewTestCase):
client = Client()
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)
self.superuser.groups.set([zb_group])
self.intervention.users.set([])
@ -265,7 +264,7 @@ class ViewTestCase(BaseViewTestCase):
def test_views_logged_in_ets_group_shared(self):
""" 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:
@ -274,7 +273,7 @@ class ViewTestCase(BaseViewTestCase):
client = Client()
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)
self.superuser.groups.set([ets_group])
self.intervention.users.set([self.superuser])
@ -334,6 +333,7 @@ class ViewTestCase(BaseViewTestCase):
self.share_create_url,
self.run_check_url,
]
# Define urls where a redirect to a specific location is the proper response
success_urls_redirect = {
self.share_url: self.detail_url
}

View File

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

View File

@ -17,3 +17,6 @@ DATA_UNSHARED_EXPLANATION = _("Remember: This data has not been shared with you,
MISSING_GROUP_PERMISSION = _("You need to be part of another user group.")
CHECKED_RECORDED_RESET = _("Status of Checked and Recorded reseted")
# ECO ACCOUNT
CANCEL_ACC_RECORDED_OR_DEDUCTED = _("Action canceled. Eco account is recorded or deductions exist. Only conservation office member can perform this action.")