import datetime from django.urls import reverse from rest_framework import status from rest_framework.test import APITestCase from apps.account.models import User from apps.profiles.models import Institution, InstitutionMember from apps.events.models import Event, EventRegistration, EventCategory, LocationType, RegistrationStatus class Phase7EventsAPITests(APITestCase): def setUp(self): # Create Users self.superadmin = User.objects.create_superuser( email="superadmin@razavi.global", password="Password123!", fullname="Super Admin" ) self.inst_admin = User.objects.create_user( email="admin@imamali.org", password="Password123!", fullname="Ali Najafi", user_type="institution_admin" ) self.member_user = User.objects.create_user( email="user@test.org", password="Password123!", fullname="Reza Moradi", user_type="client" ) self.unrelated_user = User.objects.create_user( email="stranger@test.org", password="Password123!", fullname="Stranger Person", user_type="client" ) # Create Institution self.institution = Institution.objects.create( name="Imam Ali Islamic Center", slug="imam-ali-center", type="cultural_center", country="Germany", city="Berlin", address="Center St 123", latitude=52.5200, longitude=13.4050, verification_status="approved", is_active=True ) # Add admin member InstitutionMember.objects.create( institution=self.institution, user=self.inst_admin, role="admin" ) # Create Initial Event self.event = Event.objects.create( title="International Peace & Coexistence Conference", slug="international-peace-conference", description="A global dialogue on peaceful coexistence and cultural diplomacy.", organizer=self.institution, created_by=self.inst_admin, category=EventCategory.CONFERENCE, event_date=datetime.date.today() + datetime.timedelta(days=7), start_time=datetime.time(10, 0), end_time=datetime.time(12, 30), speaker_name="Dr. Hassan Tabatabaei", speaker_title="Head of Philosophy Dept", location_type=LocationType.HYBRID, venue_address="Hall A, Berlin", online_meeting_url="https://meet.jit.si/peace-conf-2026", capacity=50, is_active=True, is_featured=True, language="en" ) def test_list_events(self): url = reverse('event-list-create') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) # Should include the event in results results = response.data.get('results', response.data) self.assertEqual(len(results), 1) self.assertEqual(results[0]['title'], self.event.title) self.assertEqual(results[0]['organizer']['name'], self.institution.name) def test_filter_events_by_category_and_search(self): url = reverse('event-list-create') # Search match response = self.client.get(url, {'search': 'Coexistence'}) results = response.data.get('results', response.data) self.assertEqual(len(results), 1) # Search no match response = self.client.get(url, {'search': 'NonexistentTopic'}) results = response.data.get('results', response.data) self.assertEqual(len(results), 0) # Category match response = self.client.get(url, {'category': 'conference'}) results = response.data.get('results', response.data) self.assertEqual(len(results), 1) # Category no match response = self.client.get(url, {'category': 'counseling'}) results = response.data.get('results', response.data) self.assertEqual(len(results), 0) def test_create_event_authorized(self): self.client.force_authenticate(user=self.inst_admin) url = reverse('event-list-create') payload = { "title": "Ramadan Quran Recitation Workshop", "description": "Daily recitation and reflection sessions.", "organizer_id": self.institution.id, "category": "workshop", "event_date": str(datetime.date.today() + datetime.timedelta(days=14)), "start_time": "18:00:00", "end_time": "19:30:00", "speaker_name": "Qari Ahmad", "location_type": "online", "capacity": 200, "language": "ar" } response = self.client.post(url, payload, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.data['title'], "Ramadan Quran Recitation Workshop") self.assertEqual(response.data['organizer']['id'], self.institution.id) def test_create_event_unauthorized_user(self): self.client.force_authenticate(user=self.unrelated_user) url = reverse('event-list-create') payload = { "title": "Unauthorized Event", "description": "Description", "organizer_id": self.institution.id, "category": "cultural", "event_date": str(datetime.date.today() + datetime.timedelta(days=10)), "start_time": "10:00:00" } response = self.client.post(url, payload, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) error_fields = [e.get('field') for e in response.data.get('errors', [])] if 'errors' in response.data else response.data self.assertTrue('organizer_id' in error_fields) def test_retrieve_event_by_id_and_slug(self): # By ID url_id = reverse('event-detail', kwargs={'id_or_slug': str(self.event.id)}) response = self.client.get(url_id) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['slug'], self.event.slug) # By Slug url_slug = reverse('event-detail', kwargs={'id_or_slug': self.event.slug}) response = self.client.get(url_slug) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['id'], self.event.id) def test_update_event_permissions(self): url = reverse('event-detail', kwargs={'id_or_slug': str(self.event.id)}) # Unauthenticated attempt response = self.client.patch(url, {"title": "New Title"}, format='json') self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) # Unrelated user attempt self.client.force_authenticate(user=self.unrelated_user) response = self.client.patch(url, {"title": "New Title"}, format='json') self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) # Authorized inst_admin attempt self.client.force_authenticate(user=self.inst_admin) response = self.client.patch(url, {"title": "Updated Peace Conference Title"}, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['title'], "Updated Peace Conference Title") def test_event_registration_flow_and_cancellation(self): self.client.force_authenticate(user=self.member_user) reg_url = reverse('event-register', kwargs={'id_or_slug': str(self.event.id)}) # Register response = self.client.post(reg_url, {"notes": "Looking forward to attending!"}, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertTrue(response.data['is_registered']) self.assertEqual(response.data['registration_count'], 1) # Duplicate registration attempt response = self.client.post(reg_url, {}, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) # Cancel registration cancel_url = reverse('event-cancel-registration', kwargs={'id_or_slug': str(self.event.id)}) response = self.client.post(cancel_url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertFalse(response.data['is_registered']) self.assertEqual(response.data['registration_count'], 0) def test_event_registrations_list_for_organizer(self): # Register a participant EventRegistration.objects.create( event=self.event, user=self.member_user, status=RegistrationStatus.REGISTERED, notes="Participant notes" ) self.event.update_registration_count() url = reverse('event-registrations-list', kwargs={'id_or_slug': str(self.event.id)}) # Unrelated user cannot view attendees self.client.force_authenticate(user=self.unrelated_user) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) # Inst admin can view attendees self.client.force_authenticate(user=self.inst_admin) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) results = response.data.get('results', response.data) self.assertEqual(len(results), 1) self.assertEqual(results[0]['user']['email'], self.member_user.email) def test_calendar_view(self): url = reverse('event-calendar') today = datetime.date.today() response = self.client.get(url, {'year': today.year, 'month': today.month}) self.assertEqual(response.status_code, status.HTTP_200_OK) results = response.data.get('results', response.data) self.assertTrue(len(results) >= 1)