* adds workflow tests for checkability and recordability for interventions
* fixes/improves code snippets detected by testing
This commit is contained in:
2021-11-11 10:37:22 +01:00
parent 34fd78be5e
commit 796990ffbc
7 changed files with 205 additions and 34 deletions

View File

@@ -182,7 +182,10 @@ class NewRevocationModalForm(BaseModalForm):
return revocation
class RunCheckModalForm(BaseModalForm):
class CheckModalForm(BaseModalForm):
""" The modal form for running a check on interventions and their compensations
"""
checked_intervention = forms.BooleanField(
label=_("Checked intervention data"),
label_suffix="",

View File

@@ -16,7 +16,7 @@
{% fa5_icon 'share-alt' %}
</button>
{% if is_zb_member %}
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Run check' %}" data-form-url="{% url 'intervention:run-check' obj.id %}">
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Run check' %}" data-form-url="{% url 'intervention:check' obj.id %}">
{% fa5_icon 'star' %}
</button>
{% endif %}

View File

@@ -30,7 +30,7 @@ class InterventionViewTestCase(BaseViewTestCase):
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.run_check_url = reverse("intervention: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,))

View File

@@ -7,13 +7,12 @@ Created on: 10.11.21
"""
import datetime
from django.contrib.auth.models import Group
from django.core.exceptions import ObjectDoesNotExist
from django.urls import reverse
from compensation.models import Payment, EcoAccountDeduction
from intervention.models import Intervention
from konova.settings import DEFAULT_GROUP
from konova.settings import DEFAULT_GROUP, ETS_GROUP, ZB_GROUP
from konova.tests.test_views import BaseWorkflowTestCase
from user.models import UserActionLogEntry, UserAction
@@ -26,11 +25,19 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
@classmethod
def setUpTestData(cls):
super().setUpTestData()
cls.new_url = reverse("intervention:new", args=())
# Add user to the default group -> give default permissions
default_group = Group.objects.get(name=DEFAULT_GROUP)
cls.superuser.groups.set([default_group])
# Give the user shared access to the dummy intervention
cls.intervention.users.add(cls.superuser)
def setUp(self) -> None:
""" Setup data before each test run
Returns:
"""
# Set the default group as only group for the user
default_group = self.groups.get(name=DEFAULT_GROUP)
self.superuser.groups.set([default_group])
def test_new(self):
"""
@@ -45,6 +52,8 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
# Define the intervention identifier for easier handling on the next lines
test_id = "Test_IDENTIFIER"
new_url = reverse("intervention:new", args=())
# Expect the new intervention does not exist yet
obj_exists = Intervention.objects.filter(
identifier=test_id
@@ -58,7 +67,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
"geometry": "",
}
response = self.client_user.post(
self.new_url,
new_url,
post_data
)
@@ -80,6 +89,118 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
self.assertIn(self.superuser, obj.users.all())
self.assertEqual(1, obj.users.count())
def test_checkability(self):
""" Tests that the intervention can only be checked if all required data has been added
Returns:
"""
check_url = reverse("intervention:check", args=(self.intervention.id,))
post_data = {
"checked_intervention": True,
"checked_comps": True,
}
# First of all, the intervention should not be checked, yet
if self.intervention.checked:
self.intervention.checked.delete()
self.intervention.refresh_from_db()
# Make sure the dummy compensation is currently not linked to the intervention,
# since the system would check on it's quality as well (and it would fail)
self.intervention.compensations.set([])
# Run request with an incomplete intervention and missing user privileges --> expect to fail
self.client_user.post(check_url, post_data)
# We expect that the intervention is still not checked now
self.intervention.refresh_from_db()
self.assertIsNone(self.intervention.checked)
# Now give the user the required privileges by adding to the registration office group
group = self.groups.get(name=ZB_GROUP)
self.superuser.groups.add(group)
# Now fill in the missing data, so the intervention is 'valid' for checking
self.intervention = self.fill_out_intervention(self.intervention)
# Then add a dummy payment, so we pass the quality check (Checks whether any kind of valid compensation exists)
payment = Payment.objects.create(amount=10.00, due_on=None, comment="No due date because test")
self.intervention.payments.add(payment)
# Run request again
self.client_user.post(check_url, post_data)
# Update intervention from db
self.intervention.refresh_from_db()
# We expect the intervention to be checked now and contains the proper data
# Attention: We check the timestamp only on the date, not the time, since the microseconds delay would result
# in an unwanted assertion error
checked = self.intervention.checked
self.assertIsNotNone(checked)
self.assertEqual(self.superuser, checked.user)
self.assertEqual(datetime.date.today(), checked.timestamp.date())
self.assertEqual(UserAction.CHECKED, checked.action)
# Expect the user action now to live in the log
self.assertIn(checked, self.intervention.log.all())
def test_recordability(self):
""" Tests that the intervention can only be recorded if all required data has been added
Returns:
"""
record_url = reverse("intervention:record", args=(self.intervention.id,))
post_data = {
"confirm": True,
}
# Make sure the dummy compensation is currently not linked to the intervention,
# since we would check on it's quality as well then
self.intervention.compensations.set([])
# First of all, the intervention should not be recorded, yet
if self.intervention.recorded:
self.intervention.recorded.delete()
self.intervention.refresh_from_db()
# Run request with an incomplete intervention and missing user privileges --> expect to fail
self.client_user.post(record_url, post_data)
# We expect that the intervention is still not recorded now
self.intervention.refresh_from_db()
self.assertIsNone(self.intervention.recorded)
# Now give the user the required privileges by adding to the ETS group
group = self.groups.get(name=ETS_GROUP)
self.superuser.groups.add(group)
# Now fill in the missing data, so the intervention is 'valid' for recording
self.intervention = self.fill_out_intervention(self.intervention)
# Then add a dummy payment, so we pass the quality check (Checks whether any kind of valid compensation exists)
payment = Payment.objects.create(amount=10.00, due_on=None, comment="No due date because test")
self.intervention.payments.add(payment)
# Run request again
self.client_user.post(record_url, post_data)
# Update intervention from db
self.intervention.refresh_from_db()
# We expect the intervention to be recorded now and contains the proper data
# Attention: We check the timestamp only on the date, not the time, since the microseconds delay would result
# in an unwanted assertion error
self.assertIsNotNone(self.intervention.recorded)
self.assertEqual(self.superuser, self.intervention.recorded.user)
self.assertEqual(datetime.date.today(), self.intervention.recorded.timestamp.date())
self.assertEqual(UserAction.RECORDED, self.intervention.recorded.action)
# Expect the user action now to live in the log
self.assertIn(self.intervention.recorded, self.intervention.log.all())
def subtest_add_payment(self):
""" Subroutine for 'normal' payment tests
@@ -89,9 +210,9 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
Returns:
"""
## Attention: Despite the fact, this url refers to a compensation app route, we test it here for the interventions.
## Reason: A payment is some kind of compensation for an intervention. Therefore it lives inside the compensation app.
## BUT: Payments are added on the intervention detail page. Therefore it's part of a regular intervention workflow.
# Attention: Despite the fact, this url refers to a compensation app route, we test it here for the interventions.
# Reason: A payment is some kind of compensation for an intervention. Therefore it lives inside the compensation app.
# BUT: Payments are added on the intervention detail page. Therefore it's part of a regular intervention workflow.
new_payment_url = reverse("compensation:pay-new", args=(self.intervention.id,))
# Make sure there are no payments on the intervention, yet

View File

@@ -8,7 +8,7 @@ Created on: 30.11.20
from django.urls import path
from intervention.views import index_view, new_view, detail_view, edit_view, remove_view, new_document_view, share_view, \
create_share_view, remove_revocation_view, new_revocation_view, run_check_view, log_view, new_deduction_view, \
create_share_view, remove_revocation_view, new_revocation_view, check_view, log_view, new_deduction_view, \
record_view, remove_document_view, get_document_view, get_revocation_view, new_id_view, report_view
app_name = "intervention"
@@ -22,7 +22,7 @@ urlpatterns = [
path('<id>/remove', remove_view, name='remove'),
path('<id>/share/<token>', share_view, name='share'),
path('<id>/share', create_share_view, name='share-create'),
path('<id>/check', run_check_view, name='run-check'),
path('<id>/check', check_view, name='check'),
path('<id>/record', record_view, name='record'),
path('<id>/report', report_view, name='report'),

View File

@@ -5,7 +5,7 @@ from django.shortcuts import render
from intervention.forms.forms import NewInterventionForm, EditInterventionForm
from intervention.forms.modalForms import ShareInterventionModalForm, NewRevocationModalForm, \
RunCheckModalForm, NewDeductionModalForm
CheckModalForm, NewDeductionModalForm
from intervention.models import Intervention, Revocation, InterventionDocument, RevocationDocument
from intervention.tables import InterventionTable
from konova.contexts import BaseContext
@@ -413,7 +413,7 @@ def create_share_view(request: HttpRequest, id: str):
@login_required
@registration_office_group_required
@shared_access_required(Intervention, "id")
def run_check_view(request: HttpRequest, id: str):
def check_view(request: HttpRequest, id: str):
""" Renders check form for an intervention
Args:
@@ -424,7 +424,7 @@ def run_check_view(request: HttpRequest, id: str):
"""
intervention = get_object_or_404(Intervention, id=id)
form = RunCheckModalForm(request.POST or None, instance=intervention, user=request.user)
form = CheckModalForm(request.POST or None, instance=intervention, user=request.user)
return form.process_request(
request,
msg_success=_("Check performed"),