456 lines
16 KiB
Python
456 lines
16 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 (
|
|
Assignment,
|
|
AssignmentCompletion,
|
|
AssignmentCompletionStatus,
|
|
AssignmentType,
|
|
)
|
|
from vbv_lernwelt.core.admin import User
|
|
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
|
|
from vbv_lernwelt.notify.services import NotificationService
|
|
|
|
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",
|
|
AssignmentType.PRAXIS_ASSIGNMENT: "test-lehrgang-lp-circle-reisen-lc-mein-kundenstamm",
|
|
}
|
|
|
|
|
|
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 action_object is 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 action_object is 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)
|
|
|
|
|
|
class TestAssignmentCourseUpdateTest(TestCase):
|
|
def setUp(self):
|
|
create_default_users()
|
|
create_test_course(with_sessions=True)
|
|
|
|
CourseSessionAssignment.objects.all().delete()
|
|
Notification.objects.all().delete()
|
|
|
|
self.student = User.objects.get(email=RECIPIENT_STUDENTS[0])
|
|
self.trainer = User.objects.get(email=RECIPIENT_TRAINER)
|
|
|
|
@freeze_time("2023-01-01")
|
|
def test_notification_title_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)),
|
|
)
|
|
assignment = Assignment.objects.get(
|
|
slug="test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice"
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.create(
|
|
completion_status=AssignmentCompletionStatus.SUBMITTED.value,
|
|
assignment_user=self.student,
|
|
assignment=assignment,
|
|
evaluation_passed=True,
|
|
course_session=casework.course_session,
|
|
completion_data={},
|
|
evaluation_max_points=10,
|
|
evaluation_points=10,
|
|
evaluation_user=self.trainer,
|
|
)
|
|
|
|
# WHEN
|
|
NotificationService.send_assignment_submitted_notification(
|
|
recipient=self.trainer,
|
|
sender=ac.assignment_user,
|
|
assignment_completion=ac,
|
|
)
|
|
|
|
# THEN
|
|
self.assertEqual(1, len(Notification.objects.all()))
|
|
|
|
notification = Notification.objects.get(recipient__username=RECIPIENT_TRAINER)
|
|
self.assertEqual("USER_INTERACTION", notification.notification_category)
|
|
self.assertIn("hat die geleitete Fallarbeit", notification.verb)
|
|
|
|
def test_notification_title_praxis_assignment_for_experts(self):
|
|
# GIVEN.
|
|
casework = create_assignment(
|
|
assignment_type=AssignmentType.PRAXIS_ASSIGNMENT,
|
|
)
|
|
assignment = Assignment.objects.get(
|
|
slug="test-lehrgang-assignment-mein-kundenstamm"
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.create(
|
|
completion_status=AssignmentCompletionStatus.SUBMITTED.value,
|
|
assignment_user=self.student,
|
|
assignment=assignment,
|
|
evaluation_passed=True,
|
|
course_session=casework.course_session,
|
|
completion_data={},
|
|
evaluation_max_points=10,
|
|
evaluation_points=10,
|
|
evaluation_user=self.trainer,
|
|
)
|
|
|
|
# WHEN
|
|
NotificationService.send_assignment_submitted_notification(
|
|
recipient=self.trainer,
|
|
sender=ac.assignment_user,
|
|
assignment_completion=ac,
|
|
)
|
|
|
|
# THEN
|
|
self.assertEqual(1, len(Notification.objects.all()))
|
|
|
|
notification = Notification.objects.get(recipient__username=RECIPIENT_TRAINER)
|
|
self.assertEqual("USER_INTERACTION", notification.notification_category)
|
|
self.assertIn("hat den Praxisauftrag", notification.verb)
|
|
|
|
@freeze_time("2023-01-01")
|
|
def test_notification_title_casework_for_student(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)),
|
|
)
|
|
assignment = Assignment.objects.get(
|
|
slug="test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice"
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.create(
|
|
completion_status=AssignmentCompletionStatus.EVALUATION_SUBMITTED.value,
|
|
assignment_user=self.student,
|
|
assignment=assignment,
|
|
evaluation_passed=True,
|
|
course_session=casework.course_session,
|
|
completion_data={},
|
|
evaluation_max_points=10,
|
|
evaluation_points=10,
|
|
evaluation_user=self.trainer,
|
|
)
|
|
|
|
# WHEN
|
|
NotificationService.send_assignment_evaluated_notification(
|
|
recipient=ac.assignment_user,
|
|
sender=self.trainer,
|
|
assignment_completion=ac,
|
|
target_url="/some/url",
|
|
)
|
|
|
|
# THEN
|
|
self.assertEqual(1, len(Notification.objects.all()))
|
|
|
|
notification = Notification.objects.get(recipient__username=self.student.email)
|
|
self.assertEqual("USER_INTERACTION", notification.notification_category)
|
|
self.assertIn("hat die geleitete Fallarbeit", notification.verb)
|
|
|
|
@freeze_time("2023-01-01")
|
|
def test_notification_title_praxis_assignment_for_student(self):
|
|
# GIVEN
|
|
casework = create_assignment(
|
|
assignment_type=AssignmentType.PRAXIS_ASSIGNMENT,
|
|
)
|
|
assignment = Assignment.objects.get(
|
|
slug="test-lehrgang-assignment-mein-kundenstamm"
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.create(
|
|
completion_status=AssignmentCompletionStatus.EVALUATION_SUBMITTED.value,
|
|
assignment_user=self.student,
|
|
assignment=assignment,
|
|
evaluation_passed=True,
|
|
course_session=casework.course_session,
|
|
completion_data={},
|
|
evaluation_max_points=10,
|
|
evaluation_points=10,
|
|
evaluation_user=self.trainer,
|
|
)
|
|
|
|
# WHEN
|
|
NotificationService.send_assignment_evaluated_notification(
|
|
recipient=ac.assignment_user,
|
|
sender=self.trainer,
|
|
assignment_completion=ac,
|
|
target_url="/some/url",
|
|
)
|
|
|
|
# THEN
|
|
self.assertEqual(1, len(Notification.objects.all()))
|
|
|
|
notification = Notification.objects.get(recipient__username=self.student.email)
|
|
self.assertEqual("USER_INTERACTION", notification.notification_category)
|
|
self.assertIn("hat den Praxisauftrag", notification.verb)
|