from itertools import chain from django.contrib.auth import get_user_model from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType from django.test import Client from hypothesis import given from hypothesis import strategies as st from hypothesis.extra.django import TestCase, from_model from paperwork.models import ( Certification, CertificationDefinition, CertificationVersion, Department, InstructorOrVendor, Waiver, ) class PermissionRequiredViewTestCaseMixin: permissions = [] path = None @classmethod def setUpTestData(cls): User = get_user_model() cls.client = Client() cls.user_without_permission = User.objects.create_user( username="user_without_permission" ) cls.user_with_permission = User.objects.create_user( username="user_with_permission" ) resolved_permissions = [ Permission.objects.get( content_type=ContentType.objects.get_for_model(permission["model"]), codename=permission["codename"], ) for permission in cls.permissions ] cls.user_with_permission.user_permissions.add(*resolved_permissions) def test_missing_permission(self) -> None: self.client.force_login(self.user_without_permission) response = self.client.get(self.path) self.assertEqual(response.status_code, 403) class WaiverReportTestCase(PermissionRequiredViewTestCaseMixin, TestCase): permissions = [{"model": Waiver, "codename": "view_waiver"}] path = "/paperwork/waivers" @given(waivers=st.lists(from_model(Waiver, number=st.none()))) def test_waiver_report(self, waivers: list[Waiver]) -> None: self.client.force_login(self.user_with_permission) response = self.client.get(self.path) self.assertEqual(response.status_code, 200) class InstructorOrVendorReportTestCase(PermissionRequiredViewTestCaseMixin, TestCase): permissions = [{"model": InstructorOrVendor, "codename": "view_instructororvendor"}] path = "/paperwork/instructors-and-vendors" @given( instructors_or_vendors=st.lists( from_model(InstructorOrVendor, serial=st.none()) ) ) def test_waiver_report( self, instructors_or_vendors: list[InstructorOrVendor] ) -> None: self.client.force_login(self.user_with_permission) response = self.client.get(self.path) self.assertEqual(response.status_code, 200) @st.composite def random_certifications( draw, ) -> list[Certification]: def certifications(version: CertificationVersion): return st.lists( from_model( Certification, number=st.none(), certification_version=st.just(version), ), max_size=10, ) def versions_with_certifications(definition: CertificationDefinition): return st.lists( from_model(CertificationVersion, definition=st.just(definition)).flatmap( certifications ), max_size=2, ) def definitions_with_versions(department: Department): return st.lists( from_model(CertificationDefinition, department=st.just(department)).flatmap( versions_with_certifications ), max_size=2, ) return draw( st.lists( from_model(Department).flatmap(definitions_with_versions), max_size=2, ).map( lambda x: list( chain.from_iterable(chain.from_iterable(chain.from_iterable(x))) ) ) ) class CertifiersReportTestCase(PermissionRequiredViewTestCaseMixin, TestCase): permissions = [{"model": Certification, "codename": "view_certification"}] path = "/paperwork/certifiers" @given(certifications=random_certifications()) def test_certifiers_report(self, certifications: list[Certification]) -> None: self.client.force_login(self.user_with_permission) response = self.client.get(self.path) self.assertEqual(response.status_code, 200) class CertificationCountReportTestCase(PermissionRequiredViewTestCaseMixin, TestCase): permissions = [{"model": Certification, "codename": "view_certification"}] path = "/paperwork/certification-count" @given(certifications=random_certifications()) def test_certification_count_report( self, certifications: list[Certification] ) -> None: self.client.force_login(self.user_with_permission) response = self.client.get(self.path) self.assertEqual(response.status_code, 200)