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())