vbv/server/vbv_lernwelt/notify/tests/test_assigment_reminders.py

287 lines
10 KiB
Python

import re
from datetime import datetime
from typing import Dict
from django.test import TestCase
from django.utils import timezone
from freezegun import freeze_time
from vbv_lernwelt.assignment.models import AssignmentType
from vbv_lernwelt.core.constants import TEST_COURSE_SESSION_BERN_ID
from vbv_lernwelt.core.create_default_users import create_default_users
from vbv_lernwelt.course.creators.test_course import create_test_course
from vbv_lernwelt.course.models import CourseSession
from vbv_lernwelt.course_session.models import (
CourseSessionAssignment,
CourseSessionEdoniqTest,
)
from vbv_lernwelt.learnpath.models import (
LearningContentAssignment,
LearningContentEdoniqTest,
)
from vbv_lernwelt.notify.email.email_services import EmailTemplate
from vbv_lernwelt.notify.email.reminders.assigment import (
send_assignment_reminder_notifications,
)
from vbv_lernwelt.notify.models import Notification
EXPECTED_MEMBER_VERB = "Erinnerung: Bald ist ein Abgabetermin"
EXPECTED_EXPERT_VERB = "Erinnerung: Bald ist ein Bewertungstermin"
RECIPIENT_TRAINER = "test-trainer1@example.com"
RECIPIENT_STUDENTS = [
"test-student1@example.com",
"test-student2@example.com",
"test-student3@example.com",
]
ASSIGNMENT_TYPE_LEARNING_CONTENT_LOOKUP: Dict[AssignmentType, str] = {
AssignmentType.CONDITION_ACCEPTANCE: "test-lehrgang-lp-circle-fahrzeug-lc-redlichkeitserklärung",
AssignmentType.PREP_ASSIGNMENT: "test-lehrgang-lp-circle-fahrzeug-lc-fahrzeug-mein-erstes-auto",
AssignmentType.REFLECTION: "test-lehrgang-lp-circle-fahrzeug-lc-reflexion",
AssignmentType.CASEWORK: "test-lehrgang-lp-circle-fahrzeug-lc-überprüfen-einer-motorfahrzeug-versicherungspolice",
}
def create_assignment(
assignment_type: AssignmentType,
submission_deadline=None,
evaluation_deadline=None,
):
assignment = CourseSessionAssignment.objects.create(
course_session=CourseSession.objects.get(id=TEST_COURSE_SESSION_BERN_ID),
learning_content=LearningContentAssignment.objects.get(
slug=ASSIGNMENT_TYPE_LEARNING_CONTENT_LOOKUP[assignment_type]
),
)
assert (
AssignmentType(assignment.learning_content.assignment_type) == assignment_type
)
if submission_deadline:
assignment.submission_deadline.start = submission_deadline
assignment.submission_deadline.end = None
assignment.submission_deadline.save()
if evaluation_deadline:
assignment.evaluation_deadline.start = evaluation_deadline
assignment.evaluation_deadline.end = None
assignment.evaluation_deadline.save()
return assignment
def create_edoniq_test_assignment(deadline_start):
edoniq_test = CourseSessionEdoniqTest.objects.create(
course_session=CourseSession.objects.get(
id=TEST_COURSE_SESSION_BERN_ID,
),
learning_content=LearningContentEdoniqTest.objects.get(
slug="test-lehrgang-lp-circle-fahrzeug-lc-wissens-und-verständnisfragen"
),
)
edoniq_test.deadline.start = deadline_start
edoniq_test.deadline.end = None
edoniq_test.deadline.save()
return edoniq_test
class TestAssignmentCourseRemindersTest(TestCase):
def setUp(self):
create_default_users()
create_test_course(with_sessions=True)
CourseSessionAssignment.objects.all().delete()
CourseSessionEdoniqTest.objects.all().delete()
Notification.objects.all().delete()
def _assert_member_assignment_notifications(
self, action_object, expected_recipients
):
for expected_recipient in expected_recipients:
notification = Notification.objects.get(
recipient__username=expected_recipient
)
self.assertEqual(action_object, notification.action_object)
self.assertEqual("ASSIGNMENT_REMINDER", notification.notification_trigger)
self.assertEqual("INFORMATION", notification.notification_category)
self.assertEqual(EXPECTED_MEMBER_VERB, notification.verb)
template_data = notification.data["template_data"]
self.assertEqual(
action_object.learning_content.get_parent_circle().title,
template_data["circle"],
)
self.assertEqual(
action_object.learning_content.get_frontend_url(),
notification.target_url,
)
match = re.fullmatch(
r"\d{2}\.\d{2}\.\d{4} \d{2}:\d{2}", template_data["due_date"]
)
self.assertIsNotNone(
match, f"due_date format is incorrect: {template_data['due_date']}"
)
email_template = notification.data["email_template"]
# make sure we have the correct email template
if type(action_object) == CourseSessionAssignment:
assignment_type = AssignmentType(
action_object.learning_content.assignment_type
)
if assignment_type == AssignmentType.CASEWORK:
self.assertEqual(
EmailTemplate.ASSIGNMENT_REMINDER_CASEWORK_MEMBER.name,
email_template,
)
elif assignment_type == AssignmentType.PREP_ASSIGNMENT:
self.assertEqual(
EmailTemplate.ASSIGNMENT_REMINDER_PREP_ASSIGNMENT_MEMBER.name,
email_template,
)
elif type(action_object) == CourseSessionEdoniqTest:
self.assertEqual(
EmailTemplate.ASSIGNMENT_REMINDER_EDONIQ_MEMBER.name,
email_template,
)
@freeze_time("2023-01-01")
def test_notification_edoniq(self):
# GIVEN
should_be_sent = create_edoniq_test_assignment(
deadline_start=timezone.make_aware(datetime(2023, 1, 2))
)
# ...too early
create_edoniq_test_assignment(
deadline_start=timezone.make_aware(datetime(2023, 1, 4))
)
# ...too late
create_edoniq_test_assignment(
deadline_start=timezone.make_aware(datetime(2022, 1, 1))
)
# WHEN
send_assignment_reminder_notifications()
# THEN
self.assertEqual(3, len(Notification.objects.all()))
self._assert_member_assignment_notifications(
action_object=should_be_sent,
expected_recipients=RECIPIENT_STUDENTS,
)
with self.assertRaises(Notification.DoesNotExist):
Notification.objects.get(recipient__username=RECIPIENT_TRAINER)
@freeze_time("2023-01-01")
def test_notification_casework_for_members(self):
# GIVEN
casework = create_assignment(
assignment_type=AssignmentType.CASEWORK,
# has a submission deadline within range -> member notification
submission_deadline=timezone.make_aware(datetime(2023, 1, 2)),
# but no evaluation deadline within range -> no expert notification
evaluation_deadline=timezone.make_aware(datetime(2023, 2, 2)),
)
# ...too early
create_assignment(
assignment_type=AssignmentType.CASEWORK,
submission_deadline=timezone.make_aware(datetime(2023, 1, 4)),
evaluation_deadline=timezone.make_aware(datetime(2023, 2, 2)),
)
# ...too late
create_assignment(
assignment_type=AssignmentType.CASEWORK,
submission_deadline=timezone.make_aware(datetime(2022, 1, 1)),
evaluation_deadline=timezone.make_aware(datetime(2022, 2, 2)),
)
# WHEN
send_assignment_reminder_notifications()
# THEN
self.assertEqual(3, len(Notification.objects.all()))
self._assert_member_assignment_notifications(
action_object=casework,
expected_recipients=RECIPIENT_STUDENTS,
)
with self.assertRaises(Notification.DoesNotExist):
Notification.objects.get(recipient__username=RECIPIENT_TRAINER)
@freeze_time("2023-01-01")
def test_notification_casework_for_experts(self):
# GIVEN
casework = create_assignment(
assignment_type=AssignmentType.CASEWORK,
submission_deadline=timezone.make_aware(datetime(2022, 12, 12)),
evaluation_deadline=timezone.make_aware(datetime(2023, 1, 2)),
)
# WHEN
send_assignment_reminder_notifications()
# THEN
self.assertEqual(1, len(Notification.objects.all()))
notification = Notification.objects.get(recipient__username=RECIPIENT_TRAINER)
self.assertEqual(casework, notification.action_object)
self.assertEqual("INFORMATION", notification.notification_category)
self.assertEqual(EXPECTED_EXPERT_VERB, notification.verb)
self.assertEqual(
casework.evaluation_deadline.url_expert, notification.target_url
)
self.assertEqual(
"CASEWORK_EXPERT_EVALUATION_REMINDER", notification.notification_trigger
)
@freeze_time("2023-01-01")
def test_notification_prep_assignment(self):
# GIVEN
prep_assignment = create_assignment(
assignment_type=AssignmentType.PREP_ASSIGNMENT,
submission_deadline=timezone.make_aware(datetime(2023, 1, 2)),
evaluation_deadline=None,
)
# ...too early
create_assignment(
assignment_type=AssignmentType.PREP_ASSIGNMENT,
submission_deadline=timezone.make_aware(datetime(2023, 1, 4)),
evaluation_deadline=None,
)
# ...too late
create_assignment(
assignment_type=AssignmentType.PREP_ASSIGNMENT,
submission_deadline=timezone.make_aware(datetime(2022, 1, 1)),
evaluation_deadline=None,
)
# WHEN
send_assignment_reminder_notifications()
# THEN
self.assertEqual(3, len(Notification.objects.all()))
self._assert_member_assignment_notifications(
action_object=prep_assignment,
expected_recipients=RECIPIENT_STUDENTS,
)
with self.assertRaises(Notification.DoesNotExist):
Notification.objects.get(recipient__username=RECIPIENT_TRAINER)