diff --git a/intervention/tests/test_workflow.py b/intervention/tests/test_workflow.py new file mode 100644 index 00000000..8646adf6 --- /dev/null +++ b/intervention/tests/test_workflow.py @@ -0,0 +1,172 @@ +""" +Author: Michel Peltriaux +Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany +Contact: michel.peltriaux@sgdnord.rlp.de +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 +from intervention.models import Intervention +from konova.settings import DEFAULT_GROUP +from konova.tests.test_views import BaseWorkflowTestCase + + +class InterventionWorkflowTestCase(BaseWorkflowTestCase): + """ This test case adds workflow tests + + """ + + @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]) + + def test_new_normal_case(self): + """ + Checks a 'normal' case of creating a new intervention. + We expect the user to be redirected as expected right away to the detail page of the new intervention. + We expect the user to be directly added to the shared user of the intervention + We expect that a minimum of data (identifier, title, (empty) geometry) can be used to create an intervention + + Returns: + + """ + # Define the intervention identifier for easier handling on the next lines + test_id = "Test_IDENTIFIER" + + # Expect the new intervention does not exist yet + obj_exists = Intervention.objects.filter( + identifier=test_id + ).exists() + self.assertFalse(obj_exists) + + # User creates a new intervention with bare minimum content, using the proper url and post data + post_data = { + "identifier": test_id, + "title": "Test_TITLE", + "geometry": "", + } + response = self.client_user.post( + self.new_url, + post_data + ) + + # Now expect the new intervention to exist in the db + try: + obj = Intervention.objects.get( + identifier=test_id + ) + self.assertEqual(obj.identifier, test_id) + except ObjectDoesNotExist: + # Fail if there is no such object + self.fail() + + expected_redirect = reverse("intervention:detail", args=(obj.id,)) + # Expect redirect to the detail view of the new intervention + self.assertRedirects(response, expected_redirect) + + # Expect user to be first and only user with shared access + self.assertIn(self.superuser, obj.users.all()) + self.assertEqual(1, obj.users.count()) + + def subtest_add_payment(self): + """ Subroutine for 'normal' payment tests + + Checks a 'normal' case of adding a payment. + We expect a new payment to be addable to an existing intervention + + 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. + new_payment_url = reverse("compensation:pay-new", args=(self.intervention.id,)) + + # Create default detail page of intervention + detail_url = reverse("intervention:detail", args=(self.intervention.id,)) + + # Make sure there are no payments on the intervention, yet + self.assertEqual(0, self.intervention.payments.count()) + + # Create form data to be sent to the url + test_amount = 10.00 + test_due = "2021-01-01" + test_comment = "test_comment" + post_data = { + "amount": test_amount, + "due": test_due, + "comment": test_comment + } + self.client_user.post( + new_payment_url, + post_data, + ) + # We do not test for any redirects in here, since the new payment url is realized using a modal, which does not + # perform any direct redirects but instead reloads the page after finisihing. + + # Make sure there is a new payment on the intervention now + self.assertEqual(1, self.intervention.payments.count()) + + # Make sure the payment contains our data + payment = self.intervention.payments.all()[0] + self.assertEqual(payment.amount, test_amount) + self.assertEqual(payment.due_on, datetime.date.fromisoformat(test_due)) + self.assertEqual(payment.comment, test_comment) + return payment + + def subtest_delete_payment(self, payment: Payment): + """ Subroutine for 'normal' payment tests + + Checks a 'normal' case of adding a payment. + We expect a payment to be deletable to an existing intervention + + Returns: + + """ + # Create removing url for the payment + remove_url = reverse("compensation:pay-remove", args=(payment.id,)) + post_data = { + "confirm": True, + } + self.client_user.post( + remove_url, + post_data + ) + + # Expect the payment to be gone from the db and therefore from the intervention as well + try: + payment.refresh_from_db() + # Well, we should not reach this next line of code, since the payment should be gone, therefore not + # refreshable -> fail! + self.fail() + except ObjectDoesNotExist: + # If we get in here, the test was fine + pass + # Now make sure the intervention has no payments anymore + self.assertEqual(0, self.intervention.payments.count()) + + def test_changing_payment_test_case(self): + """ + Checks a 'normal' case of adding a payment. + We expect a new payment to be addable to an existing intervention + We expect a payment to be deletable to an existing intervention + + Returns: + + """ + # Create new payment for the default intervention + payment = self.subtest_add_payment() + + # Now remove the payment again + self.subtest_delete_payment(payment) diff --git a/konova/tests/test_views.py b/konova/tests/test_views.py index 7e4efe44..c6d1986f 100644 --- a/konova/tests/test_views.py +++ b/konova/tests/test_views.py @@ -35,6 +35,14 @@ class BaseTestCase(TestCase): superuser_pw = "root" user_pw = "root" + @classmethod + def setUpTestData(cls): + cls.create_users() + cls.create_groups() + cls.create_dummy_intervention() + cls.create_dummy_compensation() + cls.create_dummy_eco_account() + @classmethod def create_users(cls): # Create superuser and regular user @@ -185,11 +193,7 @@ class BaseViewTestCase(BaseTestCase): @classmethod def setUpTestData(cls) -> None: - cls.create_users() - cls.create_groups() - cls.create_dummy_intervention() - cls.create_dummy_compensation() - cls.create_dummy_eco_account() + super().setUpTestData() cls.login_url = reverse("simple-sso-login") def assert_url_success(self, client: Client, urls: list): @@ -331,4 +335,23 @@ class AutocompleteTestCase(BaseViewTestCase): self.atcmplt_code_comp_reg_off, self.atcmplt_code_comp_cons_off, ] - self.assert_url_success(client, urls) \ No newline at end of file + self.assert_url_success(client, urls) + + +class BaseWorkflowTestCase(BaseTestCase): + """ + Holds base methods and attributes for workflow testing + + """ + + client_user = None + client_anon = None + + @classmethod + def setUpTestData(cls): + super().setUpTestData() + + # Create logged in client and a non-logged in client (anon) + cls.client_user = Client() + cls.client_user.login(username=cls.superuser.username, password=cls.superuser_pw) + cls.client_anon = Client()