cmsmanage/paperwork/tests.py

168 lines
5.2 KiB
Python
Raw Permalink Normal View History

import logging
2024-05-04 16:38:51 -04:00
from collections.abc import Callable
from itertools import chain
2024-05-04 16:38:51 -04:00
from typing import TypedDict
from django.contrib.auth import get_user_model
2024-05-04 16:38:51 -04:00
from django.contrib.auth.models import AbstractBaseUser, Permission
from django.contrib.contenttypes.models import ContentType
2024-05-04 16:38:51 -04:00
from django.db import models
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,
)
2024-05-04 16:38:51 -04:00
class PermissionLookup(TypedDict):
codename: str
model: type[models.Model]
class PermissionRequiredViewTestCaseMixin:
2024-05-04 16:38:51 -04:00
permissions: list[PermissionLookup] = []
path: str
client: Client
user_with_permission: AbstractBaseUser
user_without_permission: AbstractBaseUser
assertEqual: Callable
@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:
# suppress PermissionDenied messages
logger = logging.getLogger("django.request")
previous_log_level = logger.getEffectiveLevel()
logger.setLevel(logging.ERROR)
self.client.force_login(self.user_without_permission)
response = self.client.get(self.path)
self.assertEqual(response.status_code, 403)
logger.setLevel(previous_log_level)
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)