Forked from
KIF / AKPlanning
196 commits behind the upstream repository.
-
Benjamin Hättasch authored
Move AKModel views into several subfiles to improve overview and resolve problems with circular imports Introduce new modular status page handling (widgets and views) Port main status page to new structure Move AK messages status page visualization to AKSubmission (therefore, they automatically do not show up when there is no possibility to create them) Introduce status widget for virtual rooms Fix timezone issue for rendering of AK messages on status page Adapt status page URL in several views and tests
Benjamin Hättasch authoredMove AKModel views into several subfiles to improve overview and resolve problems with circular imports Introduce new modular status page handling (widgets and views) Port main status page to new structure Move AK messages status page visualization to AKSubmission (therefore, they automatically do not show up when there is no possibility to create them) Introduce status widget for virtual rooms Fix timezone issue for rendering of AK messages on status page Adapt status page URL in several views and tests
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
tests.py 9.19 KiB
import traceback
from typing import List
from django.contrib.auth.models import User
from django.contrib.messages import get_messages
from django.contrib.messages.storage.base import Message
from django.test import TestCase
from django.urls import reverse_lazy, reverse
from AKModel.models import Event, AKOwner, AKCategory, AKTrack, AKRequirement, AK, Room, AKSlot, AKOrgaMessage, \
ConstraintViolation, DefaultSlot
class BasicViewTests:
VIEWS = []
APP_NAME = ''
VIEWS_STAFF_ONLY = []
EDIT_TESTCASES = []
def setUp(self):
self.staff_user = User.objects.create(
username='Test Staff User', email='teststaff@example.com', password='staffpw',
is_staff=True, is_active=True
)
self.admin_user = User.objects.create(
username='Test Admin User', email='testadmin@example.com', password='adminpw',
is_staff=True, is_superuser=True, is_active=True
)
self.deactivated_user = User.objects.create(
username='Test Deactivated User', email='testdeactivated@example.com', password='deactivatedpw',
is_staff=True, is_active=False
)
def _name_and_url(self, view_name):
"""
Get full view name (with prefix if there is one) and url from raw view definition
:param view_name: raw definition of a view
:type view_name: (str, dict)
:return: full view name with prefix if applicable, url of the view
:rtype: str, str
"""
view_name_with_prefix = f"{self.APP_NAME}:{view_name[0]}" if self.APP_NAME != "" else view_name[0]
url = reverse(view_name_with_prefix, kwargs=view_name[1])
return view_name_with_prefix, url
def _assert_message(self, response, expected_message, msg_prefix=""):
messages:List[Message] = list(get_messages(response.wsgi_request))
msg_count = "No message shown to user"
msg_content = "Wrong message, expected '{expected_message}'"
if msg_prefix != "":
msg_count = f"{msg_prefix}: {msg_count}"
msg_content = f"{msg_prefix}: {msg_content}"
# Check that the last message correctly reports the issue
# (there might be more messages from previous calls that were not already rendered)
self.assertGreater(len(messages), 0, msg=msg_count)
self.assertEqual(messages[-1].message, expected_message, msg=msg_content)
def test_views_for_200(self):
for view_name in self.VIEWS:
view_name_with_prefix, url = self._name_and_url(view_name)
try:
response = self.client.get(url)
self.assertEqual(response.status_code, 200, msg=f"{view_name_with_prefix} ({url}) broken")
except Exception as e:
self.fail(f"An error occurred during rendering of {view_name_with_prefix} ({url}):\n\n{traceback.format_exc()}")
def test_access_control_staff_only(self):
self.client.logout()
for view_name in self.VIEWS_STAFF_ONLY:
view_name_with_prefix, url = self._name_and_url(view_name)
response = self.client.get(url)
self.assertEqual(response.status_code, 302, msg=f"{view_name_with_prefix} ({url}) accessible by non-staff")
self.client.force_login(self.staff_user)
for view_name in self.VIEWS_STAFF_ONLY:
view_name_with_prefix, url = self._name_and_url(view_name)
try:
response = self.client.get(url)
self.assertEqual(response.status_code, 200,
msg=f"{view_name_with_prefix} ({url}) should be accessible for staff (but isn't)")
except Exception as e:
self.fail(f"An error occurred during rendering of {view_name_with_prefix} ({url}):\n\n{traceback.format_exc()}")
self.client.force_login(self.deactivated_user)
for view_name in self.VIEWS_STAFF_ONLY:
view_name_with_prefix, url = self._name_and_url(view_name)
response = self.client.get(url)
self.assertEqual(response.status_code, 302,
msg=f"{view_name_with_prefix} ({url}) still accessible for deactivated user")
def _to_sendable_value(self, v):
"""
Create representation sendable via POST from form data
:param v: value to prepare
:type v: any
:return: prepared value (normally either raw value or primary key of complex object)
"""
if type(v) == list:
return [e.pk for e in v]
if type(v) == "RelatedManager":
return [e.pk for e in v.all()]
return v
def test_submit_edit_form(self):
"""
Test edit forms in the most simple way (sending them again unchanged)
"""
for testcase in self.EDIT_TESTCASES:
self._test_submit_edit_form(testcase)
def _test_submit_edit_form(self, testcase):
name, url = self._name_and_url((testcase["view"], testcase["kwargs"]))
form_name = testcase.get("form_name", "form")
expected_code = testcase.get("expected_code", 302)
if "target_view" in testcase.keys():
kwargs = testcase.get("target_kwargs", testcase["kwargs"])
_, target_url = self._name_and_url((testcase["target_view"], kwargs))
else:
target_url = url
expected_message = testcase.get("expected_message", "")
admin_user = testcase.get("admin", False)
if admin_user:
self.client.force_login(self.admin_user)
else:
self.client.logout()
response = self.client.get(url)
self.assertEqual(response.status_code, 200, msg=f"{name}: Could not load edit form via GET ({url})")
form = response.context[form_name]
data = {k:self._to_sendable_value(v) for k,v in form.initial.items()}
response = self.client.post(url, data=data)
if expected_code == 200:
self.assertEqual(response.status_code, 200, msg=f"{name}: Did not return 200 ({url}")
elif expected_code == 302:
self.assertRedirects(response, target_url, msg_prefix=f"{name}: Did not redirect ({url} -> {target_url}")
if expected_message != "":
self._assert_message(response, expected_message, msg_prefix=f"{name}")
class ModelViewTests(BasicViewTests, TestCase):
fixtures = ['model.json']
ADMIN_MODELS = [
(Event, 'event'), (AKOwner, 'akowner'), (AKCategory, 'akcategory'), (AKTrack, 'aktrack'),
(AKRequirement, 'akrequirement'), (AK, 'ak'), (Room, 'room'), (AKSlot, 'akslot'),
(AKOrgaMessage, 'akorgamessage'), (ConstraintViolation, 'constraintviolation'),
(DefaultSlot, 'defaultslot')
]
VIEWS_STAFF_ONLY = [
('admin:index', {}),
('admin:event_status', {'event_slug': 'kif42'}),
('admin:event_requirement_overview', {'event_slug': 'kif42'}),
('admin:ak_csv_export', {'event_slug': 'kif42'}),
('admin:ak_wiki_export', {'slug': 'kif42'}),
('admin:ak_delete_orga_messages', {'event_slug': 'kif42'}),
('admin:ak_slide_export', {'event_slug': 'kif42'}),
('admin:default-slots-editor', {'event_slug': 'kif42'}),
('admin:room-import', {'event_slug': 'kif42'}),
('admin:new_event_wizard_start', {}),
]
EDIT_TESTCASES = [
{'view': 'admin:default-slots-editor', 'kwargs': {'event_slug': 'kif42'}, "admin": True},
]
def test_admin(self):
self.client.force_login(self.admin_user)
for model in self.ADMIN_MODELS:
if model[1] == "event":
view_name_with_prefix, url = self._name_and_url((f'admin:new_event_wizard_start', {}))
elif model[1] == "room":
view_name_with_prefix, url = self._name_and_url((f'admin:room-new', {}))
else:
view_name_with_prefix, url = self._name_and_url((f'admin:AKModel_{model[1]}_add', {}))
response = self.client.get(url)
self.assertEqual(response.status_code, 200, msg=f"Add form for model {model[1]} ({url}) broken")
for model in self.ADMIN_MODELS:
m = model[0].objects.first()
if m is not None:
view_name_with_prefix, url = self._name_and_url((f'admin:AKModel_{model[1]}_change', {'object_id': m.pk}))
response = self.client.get(url)
self.assertEqual(response.status_code, 200, msg=f"Edit form for model {model[1]} ({url}) broken")
def test_wiki_export(self):
self.client.force_login(self.admin_user)
export_url = reverse_lazy(f"admin:ak_wiki_export", kwargs={'slug': 'kif42'})
response = self.client.get(export_url)
self.assertEqual(response.status_code, 200, "Export not working at all")
export_count = 0
for category, aks in response.context["categories_with_aks"]:
for ak in aks:
self.assertEqual(ak.include_in_export, True, f"AK with export flag set to False (pk={ak.pk}) included in export")
self.assertNotEqual(ak.pk, 1, "AK known to be excluded from export (PK 1) included in export")
export_count += 1
self.assertEqual(export_count, AK.objects.filter(event_id=2, include_in_export=True).count(),
"Wiki export contained the wrong number of AKs")