223 lines
8.3 KiB
Python
223 lines
8.3 KiB
Python
from datetime import timedelta
|
|
|
|
from django.contrib.auth.models import User
|
|
from django.test import Client, TestCase
|
|
from django.urls import reverse
|
|
from django.utils import timezone
|
|
|
|
from shiftregister.app.models import (
|
|
Helper,
|
|
LoginToken,
|
|
Message,
|
|
Room,
|
|
Shift,
|
|
ShiftRegistration,
|
|
)
|
|
|
|
from .forms import HELPER_FILTERS
|
|
|
|
|
|
class BulkMessageFilterTests(TestCase):
|
|
def setUp(self):
|
|
# Create a test user for login
|
|
self.user = User.objects.create_user(username="testuser", password="testpass")
|
|
self.client = Client()
|
|
self.client.login(username="testuser", password="testpass")
|
|
|
|
# Create test room
|
|
self.room = Room.objects.create(
|
|
name="Test Room", required_helpers=1, meeting_location="Test Location"
|
|
)
|
|
|
|
# Create test helpers
|
|
self.helper1 = Helper.objects.create(
|
|
phone="+491234567890", name="Helper 1", number_validated=True
|
|
)
|
|
self.helper2 = Helper.objects.create(
|
|
phone="+491234567891", name="Helper 2", number_validated=True
|
|
)
|
|
self.helper3 = Helper.objects.create(
|
|
phone="+491234567892", name="Helper 3", number_validated=True
|
|
)
|
|
self.helper4 = Helper.objects.create(
|
|
phone="+491234567893",
|
|
name="Helper 4",
|
|
number_validated=False, # This one should never be included
|
|
)
|
|
|
|
# Create login tokens for each helper so message text replacement works
|
|
LoginToken.objects.create(helper=self.helper1)
|
|
LoginToken.objects.create(helper=self.helper2)
|
|
LoginToken.objects.create(helper=self.helper3)
|
|
LoginToken.objects.create(helper=self.helper4)
|
|
|
|
# Create shifts
|
|
now = timezone.now()
|
|
self.current_shift = Shift.objects.create(
|
|
room=self.room,
|
|
start_at=now - timedelta(hours=1),
|
|
duration=timedelta(hours=3),
|
|
required_helpers=2,
|
|
)
|
|
self.past_shift = Shift.objects.create(
|
|
room=self.room,
|
|
start_at=now - timedelta(hours=5),
|
|
duration=timedelta(hours=2),
|
|
required_helpers=2,
|
|
)
|
|
|
|
# Create registrations
|
|
# Helper1: Has a checked-in past shift
|
|
ShiftRegistration.objects.create(
|
|
shift=self.past_shift,
|
|
helper=self.helper1,
|
|
state=ShiftRegistration.RegState.CHECKED_IN,
|
|
)
|
|
|
|
# Helper2: Currently active in a shift
|
|
ShiftRegistration.objects.create(
|
|
shift=self.current_shift,
|
|
helper=self.helper2,
|
|
state=ShiftRegistration.RegState.CHECKED_IN,
|
|
)
|
|
|
|
# Helper3: Has no shifts
|
|
# Helper4: Not validated, should never be included
|
|
|
|
def test_all_helpers_filter(self):
|
|
"""Test that 'all' filter returns all validated helpers"""
|
|
base_query = Helper.objects.filter(number_validated=True)
|
|
helpers = HELPER_FILTERS["all"]["query"](base_query)
|
|
|
|
self.assertEqual(helpers.count(), 3)
|
|
self.assertIn(self.helper1, helpers)
|
|
self.assertIn(self.helper2, helpers)
|
|
self.assertIn(self.helper3, helpers)
|
|
self.assertNotIn(self.helper4, helpers)
|
|
|
|
def test_checked_in_helpers_filter(self):
|
|
"""Test that 'checked_in' filter returns only helpers with at least one check-in"""
|
|
base_query = Helper.objects.filter(number_validated=True)
|
|
helpers = HELPER_FILTERS["checked_in"]["query"](base_query)
|
|
|
|
self.assertEqual(helpers.count(), 2)
|
|
self.assertIn(self.helper1, helpers)
|
|
self.assertIn(self.helper2, helpers)
|
|
self.assertNotIn(self.helper3, helpers)
|
|
self.assertNotIn(self.helper4, helpers)
|
|
|
|
def test_current_helpers_filter(self):
|
|
"""Test that 'current' filter returns only helpers currently in a shift"""
|
|
base_query = Helper.objects.filter(number_validated=True)
|
|
helpers = HELPER_FILTERS["current"]["query"](base_query)
|
|
|
|
self.assertEqual(helpers.count(), 1)
|
|
self.assertNotIn(self.helper1, helpers) # Past shift
|
|
self.assertIn(self.helper2, helpers) # Current shift
|
|
self.assertNotIn(self.helper3, helpers) # No shifts
|
|
self.assertNotIn(self.helper4, helpers) # Not validated
|
|
|
|
def test_no_shifts_helpers_filter(self):
|
|
"""Test that 'no_shifts' filter returns only helpers without any shift registrations"""
|
|
base_query = Helper.objects.filter(number_validated=True)
|
|
helpers = HELPER_FILTERS["no_shifts"]["query"](base_query)
|
|
|
|
self.assertEqual(helpers.count(), 1)
|
|
self.assertNotIn(self.helper1, helpers) # Has past shift
|
|
self.assertNotIn(self.helper2, helpers) # Has current shift
|
|
self.assertIn(self.helper3, helpers) # No shifts
|
|
self.assertNotIn(self.helper4, helpers) # Not validated
|
|
|
|
def test_good_helpers_filter(self):
|
|
"""Test that 'good_helpers' filter returns only helpers with check-ins and no failed shifts"""
|
|
# Add a failed shift for helper1
|
|
ShiftRegistration.objects.create(
|
|
shift=self.current_shift,
|
|
helper=self.helper1,
|
|
state=ShiftRegistration.RegState.FAILED,
|
|
)
|
|
|
|
base_query = Helper.objects.filter(number_validated=True)
|
|
helpers = HELPER_FILTERS["good_helpers"]["query"](base_query)
|
|
|
|
self.assertEqual(helpers.count(), 1)
|
|
self.assertNotIn(self.helper1, helpers) # Has a failed shift
|
|
self.assertIn(self.helper2, helpers) # Has only checked-in shifts
|
|
self.assertNotIn(self.helper3, helpers) # Has no shifts
|
|
self.assertNotIn(self.helper4, helpers) # Not validated
|
|
|
|
def test_good_helpers_no_feedback_filter(self):
|
|
"""Test that 'good_helpers_no_feedback' filter returns only good helpers without feedback"""
|
|
from shiftregister.feedback.models import Feedback
|
|
|
|
# Add feedback for helper2
|
|
Feedback.objects.create(
|
|
helper=self.helper2,
|
|
party=Feedback.PartyState.YES,
|
|
next_year=True,
|
|
)
|
|
|
|
base_query = Helper.objects.filter(number_validated=True)
|
|
helpers = HELPER_FILTERS["good_helpers_no_feedback"]["query"](base_query)
|
|
|
|
self.assertEqual(helpers.count(), 1)
|
|
self.assertIn(self.helper1, helpers) # Has no feedback
|
|
self.assertNotIn(self.helper2, helpers) # Has feedback
|
|
self.assertNotIn(self.helper3, helpers) # Has no shifts
|
|
self.assertNotIn(self.helper4, helpers) # Not validated
|
|
|
|
def test_bulk_message_view_with_filters(self):
|
|
"""Test that the bulk message view correctly applies filters"""
|
|
test_message = "Test message"
|
|
|
|
# Add a failed shift for helper1 to test good_helpers filter
|
|
ShiftRegistration.objects.create(
|
|
shift=self.current_shift,
|
|
helper=self.helper1,
|
|
state=ShiftRegistration.RegState.FAILED,
|
|
)
|
|
|
|
# Add feedback for helper2 to test good_helpers_no_feedback filter
|
|
from shiftregister.feedback.models import Feedback
|
|
|
|
Feedback.objects.create(
|
|
helper=self.helper2,
|
|
party=Feedback.PartyState.YES,
|
|
next_year=True,
|
|
)
|
|
|
|
for filter_key in HELPER_FILTERS.keys():
|
|
response = self.client.post(
|
|
reverse("team:bulk_message"),
|
|
{"message": test_message, "helper_filter": filter_key},
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
# Count messages created
|
|
if filter_key == "all":
|
|
expected_count = 3
|
|
elif filter_key == "checked_in":
|
|
expected_count = 2
|
|
elif filter_key == "current":
|
|
expected_count = 2
|
|
elif filter_key == "no_shifts":
|
|
expected_count = 1
|
|
elif filter_key == "good_helpers":
|
|
expected_count = 1
|
|
elif filter_key == "good_helpers_no_feedback":
|
|
expected_count = (
|
|
0 # but has left feedback. we cover the filter in another test
|
|
)
|
|
else:
|
|
self.fail(f"Unexpected filter key: {filter_key}")
|
|
|
|
self.assertEqual(
|
|
Message.objects.filter(text__startswith=test_message).count(),
|
|
expected_count,
|
|
f"Expected {expected_count} messages for filter '{filter_key}'",
|
|
)
|
|
|
|
# Clean up for next iteration
|
|
Message.objects.all().delete()
|