""" Author: Michel Peltriaux Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany Contact: michel.peltriaux@sgdnord.rlp.de Created on: 26.10.21 """ from abc import abstractmethod from django.contrib.auth.models import User, Group from django.test import TestCase, Client from django.urls import reverse from compensation.models import Compensation, CompensationState, CompensationAction from intervention.models import LegalData, ResponsibilityData, Intervention from konova.management.commands.setup_data import GROUPS_DATA from konova.models import Geometry from user.models import UserActionLogEntry, UserAction class BaseTestCase(TestCase): """ Provides reusable functionality for specialized test cases """ users = None groups = None superuser = None user = None superuser_pw = "root" user_pw = "root" @classmethod def create_users(cls): # Create superuser and regular user cls.superuser = User.objects.create_superuser( username="root", email="root@root.com", password=cls.superuser_pw, ) cls.user = User.objects.create_user( username="user1", email="user@root.com", password=cls.user_pw ) cls.users = User.objects.all() @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, ) cls.groups = Group.objects.all() class Meta: abstract = True class BaseViewTestCase(BaseTestCase): """ Wraps basic test functionality, reusable for every specialized ViewTestCase """ login_url = None intervention = None compensation = None comp_state = None comp_action = None @classmethod def setUpTestData(cls) -> None: cls.create_users() cls.create_groups() cls.create_dummy_intervention() cls.create_dummy_compensation() 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 Args: client (Client): The performing client urls (list): An iterable list of urls to be checked Returns: """ for url in urls: response = client.get(url) self.assertEqual(response.status_code, 200, msg=f"Failed for {url}") def assert_url_success_redirect(self, client: Client, urls: dict): """ Assert for all given urls a 302 response to a certain location. Assert the redirect being the expected behaviour. Args: client (Client): The performing client urls (dict): An iterable dict of (urls, redirect_to_url) pairs to be checked Returns: """ for url, redirect_to in urls.items(): response = client.get(url, follow=True) # Expect redirects to the landing page self.assertEqual(response.redirect_chain[0], (redirect_to, 302), msg=f"Failed for {url}") def assert_url_fail(self, client: Client, urls: list): """ Assert for all given urls a direct 302 response Args: client (Client): The performing client urls (list): An iterable list of urls to be checked Returns: """ for url in urls: response = client.get(url) self.assertEqual(response.status_code, 302, msg=f"Failed for {url}") @classmethod def create_dummy_intervention(cls): """ Creates an intervention which can be used for tests Returns: """ # Create dummy data # Create log entry action = UserActionLogEntry.objects.create( user=cls.superuser, action=UserAction.CREATED, ) # Create legal data object (without M2M laws first) legal_data = LegalData.objects.create() # Create responsible data object responsibility_data = ResponsibilityData.objects.create() geometry = Geometry.objects.create() # Finally create main object, holding the other objects cls.intervention = Intervention.objects.create( identifier="TEST", title="Test_title", responsible=responsibility_data, legal=legal_data, created=action, geometry=geometry, comment="Test", ) cls.intervention.generate_access_token(make_unique=True) @classmethod def create_dummy_compensation(cls): """ Creates an intervention 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) @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): """ Holds tests for all regular views, which are not app specific """ @classmethod def setUpTestData(cls) -> None: super().setUpTestData() cls.home_url = reverse("home") def test_views_logged_in_no_groups(self): """ Check correct status code for all requests Assumption: User logged in but has no groups Returns: """ # User logged in client = Client() client.login(username=self.superuser.username, password=self.superuser_pw) self.superuser.groups.set([]) success_urls = [ self.home_url ] self.assert_url_success(client, success_urls) def test_views_anonymous_user(self): """ Check correct status code for all requests Assumption: User logged in but has no groups Returns: """ # User not logged in client = Client() urls = [ self.home_url ] self.assert_url_fail(client, urls) class AutocompleteTestCase(BaseViewTestCase): @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 # users in a way like @loing_required or anything else. The documentation considers to check on the user's # authentication state during get_queryset() of the call. Therefore this test method here will stay here # for future clarification but won't be run due to the prefix '_' # User not logged in client = Client() urls = [ self.atcmplt_accs, self.atcmplt_interventions, self.atcmplt_code_comp_action, self.atcmplt_code_comp_funding, self.atcmplt_code_comp_biotope, self.atcmplt_code_comp_law, self.atcmplt_code_comp_process, self.atcmplt_code_comp_reg_off, self.atcmplt_code_comp_cons_off, ] self.assert_url_fail(client, urls) def test_views_logged_in_no_groups(self): # User logged in client = Client() client.login(username=self.superuser.username, password=self.superuser_pw) self.superuser.groups.set([]) urls = [ self.atcmplt_accs, self.atcmplt_interventions, self.atcmplt_code_comp_action, self.atcmplt_code_comp_funding, self.atcmplt_code_comp_biotope, self.atcmplt_code_comp_law, self.atcmplt_code_comp_process, self.atcmplt_code_comp_reg_off, self.atcmplt_code_comp_cons_off, ] self.assert_url_success(client, urls)