556 lines
20 KiB
Python
556 lines
20 KiB
Python
from datetime import date
|
|
|
|
from django.test import TestCase
|
|
from django.utils import timezone
|
|
from rest_framework import serializers
|
|
|
|
from vbv_lernwelt.assignment.models import (
|
|
Assignment,
|
|
AssignmentCompletion,
|
|
AssignmentCompletionAuditLog,
|
|
AssignmentCompletionStatus,
|
|
)
|
|
from vbv_lernwelt.assignment.services import update_assignment_completion
|
|
from vbv_lernwelt.core.create_default_users import create_default_users
|
|
from vbv_lernwelt.core.models import User
|
|
from vbv_lernwelt.core.utils import find_first
|
|
from vbv_lernwelt.course.consts import COURSE_TEST_ID
|
|
from vbv_lernwelt.course.creators.test_course import create_test_course
|
|
from vbv_lernwelt.course.models import CourseSession
|
|
from vbv_lernwelt.learnpath.models import LearningContentAssignment
|
|
|
|
|
|
class UpdateAssignmentCompletionTestCase(TestCase):
|
|
def setUp(self):
|
|
create_default_users()
|
|
self.course = create_test_course(include_vv=False)
|
|
self.assignment = (
|
|
self.course.coursepage.get_descendants()
|
|
.exact_type(Assignment)
|
|
.filter(assignment__assignment_type="CASEWORK")
|
|
.first()
|
|
.specific
|
|
)
|
|
self.course_session = CourseSession.objects.create(
|
|
course_id=COURSE_TEST_ID,
|
|
title="Bern 2022 a",
|
|
)
|
|
self.user = User.objects.get(username="student")
|
|
self.trainer = User.objects.get(username="admin")
|
|
|
|
def test_can_store_new_user_input(self):
|
|
subtasks = self.assignment.filter_user_subtasks()
|
|
user_text_input = find_first(
|
|
subtasks, pred=lambda x: x["type"] == "user_text_input"
|
|
)
|
|
user_confirmation = find_first(
|
|
subtasks, pred=lambda x: x["type"] == "user_confirmation"
|
|
)
|
|
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_data={
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Viel habe ich nicht zu sagen..."}
|
|
},
|
|
user_confirmation["id"]: {"user_data": {"confirmation": True}},
|
|
},
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.get(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
)
|
|
self.assertDictEqual(
|
|
ac.completion_data,
|
|
{
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Viel habe ich nicht zu sagen..."}
|
|
},
|
|
user_confirmation["id"]: {"user_data": {"confirmation": True}},
|
|
},
|
|
)
|
|
|
|
def test_can_update_user_input(self):
|
|
subtasks = self.assignment.filter_user_subtasks(
|
|
subtask_types=["user_text_input"]
|
|
)
|
|
user_text_input0 = subtasks[0]
|
|
user_text_input1 = subtasks[1]
|
|
|
|
ac = AssignmentCompletion.objects.create(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_data={
|
|
user_text_input0["id"]: {
|
|
"user_data": {"text": "Am Anfang war das Wort... 0"}
|
|
},
|
|
user_text_input1["id"]: {
|
|
"user_data": {"text": "Am Anfang war das Wort... 1"}
|
|
},
|
|
},
|
|
)
|
|
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_data={
|
|
user_text_input1["id"]: {
|
|
"user_data": {"text": "Viel mehr gibt es nicht zu sagen."}
|
|
}
|
|
},
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.get(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
)
|
|
user_input0 = ac.completion_data[user_text_input0["id"]]["user_data"]["text"]
|
|
user_input1 = ac.completion_data[user_text_input1["id"]]["user_data"]["text"]
|
|
self.assertEqual(user_input0, "Am Anfang war das Wort... 0")
|
|
self.assertEqual(user_input1, "Viel mehr gibt es nicht zu sagen.")
|
|
|
|
def test_will_not_store_unknown_user_tasks(self):
|
|
random_uuid = "7b60903b-d2a5-4798-b6cd-5b51e63e98ab"
|
|
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_data={
|
|
random_uuid: {
|
|
"user_data": {"text": "Viel mehr gibt es nicht zu sagen."}
|
|
}
|
|
},
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.get(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
)
|
|
self.assertEqual(ac.completion_data, {})
|
|
|
|
def test_completion_status_submitted(self):
|
|
subtasks = self.assignment.filter_user_subtasks(
|
|
subtask_types=["user_text_input"]
|
|
)
|
|
user_text_input0 = subtasks[0]
|
|
user_text_input1 = subtasks[1]
|
|
|
|
AssignmentCompletion.objects.create(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_data={
|
|
user_text_input0["id"]: {
|
|
"user_data": {"text": "Am Anfang war das Wort... 0"}
|
|
},
|
|
user_text_input1["id"]: {
|
|
"user_data": {"text": "Am Anfang war das Wort... 1"}
|
|
},
|
|
},
|
|
)
|
|
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_status=AssignmentCompletionStatus.SUBMITTED,
|
|
evaluation_user=self.trainer,
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.get(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
)
|
|
|
|
self.assertEqual(ac.completion_status, "SUBMITTED")
|
|
self.assertEqual(ac.submitted_at.date(), date.today())
|
|
self.assertEqual(ac.evaluation_user, self.trainer)
|
|
|
|
# will create AssignmentCompletionAuditLog entry
|
|
acl = AssignmentCompletionAuditLog.objects.get(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_status="SUBMITTED",
|
|
)
|
|
self.assertEqual(acl.created_at.date(), date.today())
|
|
self.assertEqual(acl.assignment_user_email, "student")
|
|
self.assertEqual(
|
|
acl.assignment_slug,
|
|
"test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice",
|
|
)
|
|
|
|
# AssignmentCompletionAuditLog entry will remain event after deletion of foreign keys
|
|
ac.delete()
|
|
self.user.delete()
|
|
self.course.coursepage.get_descendants().exact_type(
|
|
LearningContentAssignment
|
|
).delete()
|
|
self.assignment.delete()
|
|
acl = AssignmentCompletionAuditLog.objects.get(id=acl.id)
|
|
self.assertEqual(acl.created_at.date(), date.today())
|
|
self.assertEqual(acl.assignment_user_email, "student")
|
|
self.assertEqual(
|
|
acl.assignment_slug,
|
|
"test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice",
|
|
)
|
|
self.assertIsNone(acl.assignment_user)
|
|
self.assertIsNone(acl.assignment)
|
|
|
|
def test_completion_status_submitted_cannot_submit_twice(self):
|
|
subtasks = self.assignment.filter_user_subtasks(
|
|
subtask_types=["user_text_input"]
|
|
)
|
|
user_text_input0 = subtasks[0]
|
|
user_text_input1 = subtasks[1]
|
|
|
|
ac = AssignmentCompletion.objects.create(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
submitted_at=timezone.now(),
|
|
completion_status=AssignmentCompletionStatus.SUBMITTED.value,
|
|
completion_data={
|
|
user_text_input0["id"]: {
|
|
"user_data": {"text": "Am Anfang war das Wort... 0"}
|
|
},
|
|
user_text_input1["id"]: {
|
|
"user_data": {"text": "Am Anfang war das Wort... 1"}
|
|
},
|
|
},
|
|
)
|
|
|
|
with self.assertRaises(serializers.ValidationError):
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_status=AssignmentCompletionStatus.SUBMITTED,
|
|
)
|
|
|
|
# can submit twice with flag
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_status=AssignmentCompletionStatus.SUBMITTED,
|
|
validate_completion_status_change=False,
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.get(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
)
|
|
|
|
self.assertEqual(ac.completion_status, "SUBMITTED")
|
|
self.assertEqual(ac.submitted_at.date(), date.today())
|
|
|
|
def test_copy_task_data(self):
|
|
subtasks = self.assignment.filter_user_subtasks(
|
|
subtask_types=["user_text_input"]
|
|
)
|
|
user_text_input = find_first(
|
|
subtasks,
|
|
pred=lambda x: (value := x.get("value"))
|
|
and value.get("text", "").startswith(
|
|
"Gibt es zusätzliche Deckungen, die du der Person empfehlen würdest?"
|
|
),
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.create(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_data={
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Ich würde nichts weiteres empfehlen."}
|
|
},
|
|
},
|
|
)
|
|
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_status=AssignmentCompletionStatus.SUBMITTED,
|
|
copy_task_data=True,
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.get(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
)
|
|
|
|
self.assertEqual(ac.completion_status, "SUBMITTED")
|
|
user_input = ac.completion_data[user_text_input["id"]]
|
|
self.assertEqual(
|
|
user_input["user_data"]["text"], "Ich würde nichts weiteres empfehlen."
|
|
)
|
|
self.assertTrue(
|
|
user_input["value"]["text"].startswith(
|
|
"Gibt es zusätzliche Deckungen, die du der Person empfehlen würdest?"
|
|
)
|
|
)
|
|
|
|
def test_can_evaluate_with_evaluation_tasks(self):
|
|
ac = AssignmentCompletion.objects.create(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_status=AssignmentCompletionStatus.SUBMITTED,
|
|
)
|
|
|
|
evaluation_task = self.assignment.get_evaluation_tasks()[0]
|
|
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_data={
|
|
evaluation_task["id"]: {
|
|
"expert_data": {"points": 2, "text": "Gut gemacht!"}
|
|
},
|
|
},
|
|
completion_status=AssignmentCompletionStatus.EVALUATION_IN_PROGRESS,
|
|
evaluation_user=self.trainer,
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.get(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
)
|
|
|
|
self.assertEqual(ac.completion_status, "EVALUATION_IN_PROGRESS")
|
|
trainer_input = ac.completion_data[evaluation_task["id"]]
|
|
self.assertDictEqual(
|
|
trainer_input["expert_data"], {"points": 2, "text": "Gut gemacht!"}
|
|
)
|
|
|
|
def test_can_add_evaluation_data_without_loosing_user_input_data(self):
|
|
subtasks = self.assignment.filter_user_subtasks(
|
|
subtask_types=["user_text_input"]
|
|
)
|
|
user_text_input = find_first(
|
|
subtasks,
|
|
pred=lambda x: (value := x.get("value"))
|
|
and value.get("text", "").startswith(
|
|
"Gibt es zusätzliche Deckungen, die du der Person empfehlen würdest?"
|
|
),
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.create(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_status=AssignmentCompletionStatus.SUBMITTED,
|
|
completion_data={
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Ich würde nichts weiteres empfehlen."}
|
|
},
|
|
},
|
|
)
|
|
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_data={
|
|
user_text_input["id"]: {
|
|
"expert_data": {"points": 1, "comment": "Gut gemacht!"}
|
|
},
|
|
},
|
|
completion_status=AssignmentCompletionStatus.EVALUATION_IN_PROGRESS,
|
|
evaluation_user=self.trainer,
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.get(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
)
|
|
|
|
self.assertEqual(ac.completion_status, "EVALUATION_IN_PROGRESS")
|
|
user_input = ac.completion_data[user_text_input["id"]]
|
|
self.assertDictEqual(
|
|
user_input["expert_data"], {"points": 1, "comment": "Gut gemacht!"}
|
|
)
|
|
self.assertEqual(
|
|
user_input["user_data"]["text"], "Ich würde nichts weiteres empfehlen."
|
|
)
|
|
|
|
def test_cannot_evaluate_data_without_evaluation_user(self):
|
|
subtasks = self.assignment.filter_user_subtasks(
|
|
subtask_types=["user_text_input"]
|
|
)
|
|
user_text_input = find_first(
|
|
subtasks,
|
|
pred=lambda x: (value := x.get("value"))
|
|
and value.get("text", "").startswith(
|
|
"Gibt es zusätzliche Deckungen, die du der Person empfehlen würdest?"
|
|
),
|
|
)
|
|
|
|
AssignmentCompletion.objects.create(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_status=AssignmentCompletionStatus.IN_PROGRESS.value,
|
|
completion_data={
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Ich würde nichts weiteres empfehlen."}
|
|
},
|
|
},
|
|
)
|
|
|
|
with self.assertRaises(serializers.ValidationError) as error:
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_status=AssignmentCompletionStatus.EVALUATION_IN_PROGRESS,
|
|
completion_data={
|
|
user_text_input["id"]: {
|
|
"expert_data": {"points": 1, "comment": "Gut gemacht!"}
|
|
},
|
|
},
|
|
)
|
|
|
|
self.assertTrue(
|
|
"evaluation_user" in error.exception.detail,
|
|
)
|
|
|
|
def test_can_submit_evaluation(self):
|
|
subtasks = self.assignment.filter_user_subtasks(
|
|
subtask_types=["user_text_input"]
|
|
)
|
|
user_text_input = find_first(
|
|
subtasks,
|
|
pred=lambda x: (value := x.get("value"))
|
|
and value.get("text", "").startswith(
|
|
"Gibt es zusätzliche Deckungen, die du der Person empfehlen würdest?"
|
|
),
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.create(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_status=AssignmentCompletionStatus.SUBMITTED.value,
|
|
completion_data={
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Ich würde nichts weiteres empfehlen."}
|
|
},
|
|
},
|
|
)
|
|
|
|
evaluation_task = self.assignment.get_evaluation_tasks()[0]
|
|
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_data={
|
|
evaluation_task["id"]: {
|
|
"expert_data": {"points": 2, "text": "Gut gemacht!"}
|
|
},
|
|
},
|
|
completion_status=AssignmentCompletionStatus.EVALUATION_IN_PROGRESS,
|
|
evaluation_user=self.trainer,
|
|
)
|
|
|
|
with self.assertRaises(serializers.ValidationError):
|
|
# not setting grade will raise an error
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_data={},
|
|
completion_status=AssignmentCompletionStatus.EVALUATION_SUBMITTED,
|
|
evaluation_user=self.trainer,
|
|
evaluation_points=None,
|
|
)
|
|
|
|
update_assignment_completion(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_data={},
|
|
completion_status=AssignmentCompletionStatus.EVALUATION_SUBMITTED,
|
|
evaluation_user=self.trainer,
|
|
evaluation_points=16,
|
|
)
|
|
|
|
ac = AssignmentCompletion.objects.get(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
)
|
|
|
|
self.assertEqual(ac.completion_status, "EVALUATION_SUBMITTED")
|
|
self.assertEqual(ac.evaluation_points, 16)
|
|
self.assertEqual(ac.evaluation_max_points, 24)
|
|
self.assertTrue(ac.evaluation_passed)
|
|
trainer_input = ac.completion_data[evaluation_task["id"]]
|
|
self.assertDictEqual(
|
|
trainer_input["expert_data"], {"points": 2, "text": "Gut gemacht!"}
|
|
)
|
|
user_input = ac.completion_data[user_text_input["id"]]
|
|
self.assertDictEqual(
|
|
user_input["user_data"], {"text": "Ich würde nichts weiteres empfehlen."}
|
|
)
|
|
|
|
# will create AssignmentCompletionAuditLog entry
|
|
acl = AssignmentCompletionAuditLog.objects.get(
|
|
assignment_user=self.user,
|
|
assignment=self.assignment,
|
|
course_session=self.course_session,
|
|
completion_status="EVALUATION_SUBMITTED",
|
|
)
|
|
self.assertEqual(acl.created_at.date(), date.today())
|
|
self.assertEqual(acl.assignment_user_email, "student")
|
|
self.assertEqual(
|
|
acl.assignment_slug,
|
|
"test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice",
|
|
)
|
|
trainer_input = acl.completion_data[evaluation_task["id"]]
|
|
self.assertDictEqual(
|
|
trainer_input["expert_data"], {"points": 2, "text": "Gut gemacht!"}
|
|
)
|
|
user_input = acl.completion_data[user_text_input["id"]]
|
|
self.assertDictEqual(
|
|
user_input["user_data"], {"text": "Ich würde nichts weiteres empfehlen."}
|
|
)
|
|
self.assertEqual(acl.evaluation_points, 16)
|
|
self.assertEqual(acl.evaluation_max_points, 24)
|
|
self.assertTrue(acl.evaluation_passed)
|
|
|
|
# AssignmentCompletionAuditLog entry will remain event after deletion of foreign keys
|
|
ac.delete()
|
|
self.user.delete()
|
|
self.course.coursepage.get_descendants().exact_type(
|
|
LearningContentAssignment
|
|
).delete()
|
|
self.assignment.delete()
|
|
acl = AssignmentCompletionAuditLog.objects.get(id=acl.id)
|
|
self.assertEqual(acl.created_at.date(), date.today())
|
|
self.assertEqual(acl.assignment_user_email, "student")
|
|
self.assertEqual(
|
|
acl.assignment_slug,
|
|
"test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice",
|
|
)
|
|
self.assertIsNone(acl.assignment_user)
|
|
self.assertIsNone(acl.assignment)
|