#19 Tests
* adds workflow tests for checkability and recordability for interventions * fixes/improves code snippets detected by testing
This commit is contained in:
parent
34fd78be5e
commit
796990ffbc
@ -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="",
|
||||
|
@ -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 %}
|
||||
|
@ -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,))
|
||||
|
||||
|
@ -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
|
||||
|
@ -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'),
|
||||
|
||||
|
@ -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"),
|
||||
|
@ -5,13 +5,15 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
||||
Created on: 26.10.21
|
||||
|
||||
"""
|
||||
from abc import abstractmethod
|
||||
import datetime
|
||||
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.contrib.gis.geos import MultiPolygon, Polygon
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.test import TestCase, Client
|
||||
from django.urls import reverse
|
||||
|
||||
from codelist.models import KonovaCode
|
||||
from compensation.models import Compensation, CompensationState, CompensationAction, EcoAccount
|
||||
from intervention.models import LegalData, ResponsibilityData, Intervention
|
||||
from konova.management.commands.setup_data import GROUPS_DATA
|
||||
@ -32,17 +34,22 @@ class BaseTestCase(TestCase):
|
||||
eco_account = None
|
||||
comp_state = None
|
||||
comp_action = None
|
||||
codes = None
|
||||
|
||||
superuser_pw = "root"
|
||||
user_pw = "root"
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
cls.create_users()
|
||||
cls.create_groups()
|
||||
cls.create_dummy_intervention()
|
||||
cls.create_dummy_compensation()
|
||||
cls.create_dummy_eco_account()
|
||||
cls.intervention = cls.create_dummy_intervention()
|
||||
cls.compensation = cls.create_dummy_compensation()
|
||||
cls.eco_account = cls.create_dummy_eco_account()
|
||||
cls.codes = cls.create_dummy_codes()
|
||||
|
||||
@classmethod
|
||||
def create_users(cls):
|
||||
@ -69,9 +76,6 @@ class BaseTestCase(TestCase):
|
||||
)
|
||||
cls.groups = Group.objects.all()
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
@classmethod
|
||||
def create_dummy_intervention(cls):
|
||||
""" Creates an intervention which can be used for tests
|
||||
@ -91,7 +95,7 @@ class BaseTestCase(TestCase):
|
||||
responsibility_data = ResponsibilityData.objects.create()
|
||||
geometry = Geometry.objects.create()
|
||||
# Finally create main object, holding the other objects
|
||||
cls.intervention = Intervention.objects.create(
|
||||
intervention = Intervention.objects.create(
|
||||
identifier="TEST",
|
||||
title="Test_title",
|
||||
responsible=responsibility_data,
|
||||
@ -100,8 +104,8 @@ class BaseTestCase(TestCase):
|
||||
geometry=geometry,
|
||||
comment="Test",
|
||||
)
|
||||
cls.intervention.generate_access_token(make_unique=True)
|
||||
return cls.intervention
|
||||
intervention.generate_access_token(make_unique=True)
|
||||
return intervention
|
||||
|
||||
@classmethod
|
||||
def create_dummy_compensation(cls):
|
||||
@ -111,7 +115,7 @@ class BaseTestCase(TestCase):
|
||||
|
||||
"""
|
||||
if cls.intervention is None:
|
||||
cls.create_dummy_intervention()
|
||||
cls.intervention = cls.create_dummy_intervention()
|
||||
# Create dummy data
|
||||
# Create log entry
|
||||
action = UserActionLogEntry.objects.create(
|
||||
@ -120,7 +124,7 @@ class BaseTestCase(TestCase):
|
||||
)
|
||||
geometry = Geometry.objects.create()
|
||||
# Finally create main object, holding the other objects
|
||||
cls.compensation = Compensation.objects.create(
|
||||
compensation = Compensation.objects.create(
|
||||
identifier="TEST",
|
||||
title="Test_title",
|
||||
intervention=cls.intervention,
|
||||
@ -128,8 +132,7 @@ class BaseTestCase(TestCase):
|
||||
geometry=geometry,
|
||||
comment="Test",
|
||||
)
|
||||
cls.intervention.generate_access_token(make_unique=True)
|
||||
return cls.compensation
|
||||
return compensation
|
||||
|
||||
@classmethod
|
||||
def create_dummy_eco_account(cls):
|
||||
@ -149,7 +152,7 @@ class BaseTestCase(TestCase):
|
||||
lega_data = LegalData.objects.create()
|
||||
responsible_data = ResponsibilityData.objects.create()
|
||||
# Finally create main object, holding the other objects
|
||||
cls.eco_account = EcoAccount.objects.create(
|
||||
eco_account = EcoAccount.objects.create(
|
||||
identifier="TEST",
|
||||
title="Test_title",
|
||||
legal=lega_data,
|
||||
@ -158,7 +161,7 @@ class BaseTestCase(TestCase):
|
||||
geometry=geometry,
|
||||
comment="Test",
|
||||
)
|
||||
return cls.eco_account
|
||||
return eco_account
|
||||
|
||||
@classmethod
|
||||
def create_dummy_states(cls):
|
||||
@ -185,6 +188,47 @@ class BaseTestCase(TestCase):
|
||||
)
|
||||
return cls.comp_action
|
||||
|
||||
@classmethod
|
||||
def create_dummy_codes(cls):
|
||||
""" Creates some dummy KonovaCodes which can be used for testing
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
codes = KonovaCode.objects.bulk_create([
|
||||
KonovaCode(id=1, is_selectable=True, long_name="Test1"),
|
||||
KonovaCode(id=2, is_selectable=True, long_name="Test2"),
|
||||
KonovaCode(id=3, is_selectable=True, long_name="Test3"),
|
||||
KonovaCode(id=4, is_selectable=True, long_name="Test4"),
|
||||
])
|
||||
return codes
|
||||
|
||||
@staticmethod
|
||||
def fill_out_intervention(intervention: Intervention) -> Intervention:
|
||||
""" Adds all required (dummy) data to an intervention
|
||||
|
||||
Args:
|
||||
intervention (Intervention): The intervention which shall be filled out
|
||||
|
||||
Returns:
|
||||
intervention (Intervention): The modified intervention
|
||||
"""
|
||||
intervention.responsible.registration_office = KonovaCode.objects.get(id=1)
|
||||
intervention.responsible.conservation_office = KonovaCode.objects.get(id=2)
|
||||
intervention.responsible.registration_file_number = "test"
|
||||
intervention.responsible.conservation_file_number = "test"
|
||||
intervention.responsible.handler = "handler"
|
||||
intervention.responsible.save()
|
||||
intervention.legal.registration_date = datetime.date.fromisoformat("1970-01-01")
|
||||
intervention.legal.binding_date = datetime.date.fromisoformat("1970-01-01")
|
||||
intervention.legal.process_type = KonovaCode.objects.get(id=3)
|
||||
intervention.legal.save()
|
||||
intervention.legal.laws.set([KonovaCode.objects.get(id=(4))])
|
||||
intervention.geometry.geom = MultiPolygon(Polygon.from_bbox([-4.526367, 18.354526, -1.801758, 20.591652]))
|
||||
intervention.geometry.save()
|
||||
intervention.save()
|
||||
return intervention
|
||||
|
||||
|
||||
class BaseViewTestCase(BaseTestCase):
|
||||
""" Wraps basic test functionality, reusable for every specialized ViewTestCase
|
||||
@ -348,6 +392,9 @@ class BaseWorkflowTestCase(BaseTestCase):
|
||||
client_user = None
|
||||
client_anon = None
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super().setUpTestData()
|
||||
|
Loading…
Reference in New Issue
Block a user