145 lines
7.6 KiB
Python
145 lines
7.6 KiB
Python
from django.test import TestCase
|
|
from django.contrib.auth import get_user_model
|
|
from rest_framework.test import APIClient
|
|
from rest_framework import status
|
|
from .models import Skill, Event, TaskArea, Shift, ShiftSignup
|
|
|
|
User = get_user_model()
|
|
|
|
class EventAndShiftTests(TestCase):
|
|
def setUp(self):
|
|
self.client = APIClient()
|
|
self.skill = Skill.objects.create(name="Ersthelfer", color="#ef4444")
|
|
self.user = User.objects.create_user(
|
|
username="doctor_who", email="doctor@tardis.org", password="password123", display_name="Dr. Who"
|
|
)
|
|
self.event = Event.objects.create(title="Sommerfest", start_date="2026-08-10", end_date="2026-08-12")
|
|
self.ta = TaskArea.objects.create(event=self.event, name="Sanitätsdienst")
|
|
self.shift = Shift.objects.create(
|
|
task_area=self.ta, title="Hauptschicht", start_time="10:00", end_time="18:00", max_participants=2
|
|
)
|
|
self.shift.required_skills.add(self.skill)
|
|
|
|
def test_guest_cannot_signup_for_skill_required_shift(self):
|
|
res = self.client.post(f'/api/shifts/{self.shift.id}/signup/', {
|
|
'guest_name': 'Guest User',
|
|
'captcha_token': 'test-captcha-token'
|
|
})
|
|
self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST)
|
|
self.assertIn('Gäste können keine Fähigkeiten haben', res.data['error'])
|
|
|
|
def test_user_without_skill_blocked_and_with_skill_allowed(self):
|
|
self.client.force_authenticate(user=self.user)
|
|
|
|
# Attempt signup without skill
|
|
res_fail = self.client.post(f'/api/shifts/{self.shift.id}/signup/')
|
|
self.assertEqual(res_fail.status_code, status.HTTP_400_BAD_REQUEST)
|
|
self.assertIn('Dir fehlen folgende erforderliche Fähigkeiten', res_fail.data['error'])
|
|
|
|
# Add skill to user
|
|
self.user.skills.add(self.skill)
|
|
|
|
# Attempt signup with skill
|
|
res_ok = self.client.post(f'/api/shifts/{self.shift.id}/signup/')
|
|
self.assertEqual(res_ok.status_code, status.HTTP_201_CREATED)
|
|
|
|
def test_guest_privacy_redaction_in_matrix(self):
|
|
# Add signup
|
|
self.user.skills.add(self.skill)
|
|
ShiftSignup.objects.create(shift=self.shift, user=self.user)
|
|
|
|
# Unauthenticated request (Guest)
|
|
anon_client = APIClient()
|
|
res_anon = anon_client.get(f'/api/events/{self.event.id}/matrix/')
|
|
self.assertEqual(res_anon.status_code, status.HTTP_200_OK)
|
|
signup_data_anon = res_anon.data['task_areas'][0]['shifts'][0]['signups'][0]
|
|
self.assertEqual(signup_data_anon['display_name'], 'Belegt (Anonym)')
|
|
|
|
# Authenticated request
|
|
self.client.force_authenticate(user=self.user)
|
|
res_auth = self.client.get(f'/api/events/{self.event.id}/matrix/')
|
|
self.assertEqual(res_auth.status_code, status.HTTP_200_OK)
|
|
signup_data_auth = res_auth.data['task_areas'][0]['shifts'][0]['signups'][0]
|
|
self.assertEqual(signup_data_auth['display_name'], 'Dr. Who')
|
|
|
|
def test_event_edit_and_deactivation_permissions(self):
|
|
admin = User.objects.create_user(
|
|
username="admin_user", email="admin@verein.de", password="password123", is_admin_user=True
|
|
)
|
|
other_user = User.objects.create_user(
|
|
username="other_user", email="other@verein.de", password="password123"
|
|
)
|
|
user_event = Event.objects.create(
|
|
title="User Event", start_date="2026-09-01", end_date="2026-09-02", created_by=self.user
|
|
)
|
|
|
|
# Other user cannot deactivate user_event
|
|
self.client.force_authenticate(user=other_user)
|
|
res_fail = self.client.patch(f'/api/events/{user_event.id}/', {'is_active': False})
|
|
self.assertEqual(res_fail.status_code, status.HTTP_403_FORBIDDEN)
|
|
|
|
# Creator (self.user) CAN deactivate their own event
|
|
self.client.force_authenticate(user=self.user)
|
|
res_creator_ok = self.client.patch(f'/api/events/{user_event.id}/', {'is_active': False})
|
|
self.assertEqual(res_creator_ok.status_code, status.HTTP_200_OK)
|
|
self.assertFalse(res_creator_ok.data['is_active'])
|
|
|
|
# Admin CAN manage and reactivate any event
|
|
self.client.force_authenticate(user=admin)
|
|
res_admin_ok = self.client.patch(f'/api/events/{user_event.id}/', {'is_active': True})
|
|
self.assertEqual(res_admin_ok.status_code, status.HTTP_200_OK)
|
|
self.assertTrue(res_admin_ok.data['is_active'])
|
|
|
|
def test_shift_and_participant_management_permissions(self):
|
|
creator = User.objects.create_user(username="creator", email="creator@verein.de", password="password123")
|
|
other_user = User.objects.create_user(username="other", email="other@verein.de", password="password123")
|
|
|
|
event = Event.objects.create(title="Creator Event", start_date="2026-09-01", end_date="2026-09-02", created_by=creator)
|
|
ta = TaskArea.objects.create(event=event, name="Bar")
|
|
shift = Shift.objects.create(task_area=ta, title="Abendschicht", start_time="19:00", end_time="23:00", max_participants=2)
|
|
|
|
signup = ShiftSignup.objects.create(shift=shift, user=other_user)
|
|
|
|
# Other user CANNOT remove creator's participant from creator's shift
|
|
third_user = User.objects.create_user(username="third", email="third@verein.de", password="password123")
|
|
self.client.force_authenticate(user=third_user)
|
|
res_fail = self.client.delete(f'/api/shifts/{shift.id}/signup/', {'signup_id': signup.id}, format='json')
|
|
self.assertEqual(res_fail.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
# Creator CAN remove participant from shift on their own event
|
|
self.client.force_authenticate(user=creator)
|
|
res_ok = self.client.delete(f'/api/shifts/{shift.id}/signup/', {'signup_id': signup.id}, format='json')
|
|
self.assertEqual(res_ok.status_code, status.HTTP_200_OK)
|
|
self.assertFalse(ShiftSignup.objects.filter(pk=signup.id).exists())
|
|
|
|
def test_co_manager_permissions_and_guest_skill_bypass(self):
|
|
owner = User.objects.create_user(username="owner_user", email="owner@test.de", password="password123")
|
|
co_manager = User.objects.create_user(username="comanager", email="comanager@test.de", password="password123")
|
|
|
|
event = Event.objects.create(title="CoManaged Event", start_date="2026-10-01", end_date="2026-10-02", created_by=owner)
|
|
event.co_managers.add(co_manager)
|
|
|
|
ta = TaskArea.objects.create(event=event, name="Einlass")
|
|
shift = Shift.objects.create(task_area=ta, title="Spätschicht", start_time="20:00", end_time="24:00", max_participants=5)
|
|
shift.required_skills.add(self.skill)
|
|
|
|
# Co-manager can edit event
|
|
self.client.force_authenticate(user=co_manager)
|
|
res_edit = self.client.patch(f'/api/events/{event.id}/', {'location': 'Haupteingang'})
|
|
self.assertEqual(res_edit.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(res_edit.data['location'], 'Haupteingang')
|
|
|
|
# Co-manager CAN register a guest on skill-required shift (skill check bypassed for manager!)
|
|
res_guest = self.client.post(f'/api/shifts/{shift.id}/signup/', {'guest_name': 'VIP Gast'}, format='json')
|
|
self.assertEqual(res_guest.status_code, status.HTTP_201_CREATED)
|
|
self.assertIn('ohne Qualifikationsprüfung', res_guest.data['message'])
|
|
|
|
# Check signup exists
|
|
signup_id = res_guest.data['signup_id']
|
|
signup = ShiftSignup.objects.get(pk=signup_id)
|
|
self.assertEqual(signup.guest_name, 'VIP Gast')
|
|
|
|
# Co-manager can delete any signup
|
|
res_del = self.client.delete(f'/api/shifts/{shift.id}/signup/', {'signup_id': signup_id}, format='json')
|
|
self.assertEqual(res_del.status_code, status.HTTP_200_OK)
|