564 lines
20 KiB
Python
564 lines
20 KiB
Python
import json
|
|
from datetime import date
|
|
|
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
|
from django.utils import timezone
|
|
from graphene_django.utils import GraphQLTestCase
|
|
|
|
from vbv_lernwelt.assignment.models import (
|
|
Assignment,
|
|
AssignmentCompletion,
|
|
AssignmentCompletionAuditLog,
|
|
)
|
|
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.creators.test_course import create_test_course
|
|
from vbv_lernwelt.course.models import CourseSession
|
|
from vbv_lernwelt.files.models import UploadFile
|
|
from vbv_lernwelt.notify.models import Notification
|
|
|
|
|
|
class AttendanceCourseUserMutationTestCase(GraphQLTestCase):
|
|
GRAPHQL_URL = "/server/graphql/"
|
|
|
|
def setUp(self):
|
|
create_default_users()
|
|
create_test_course(include_vv=False, with_sessions=True)
|
|
self.course_session = CourseSession.objects.get(title="Test Bern 2022 a")
|
|
self.trainer = User.objects.get(username="test-trainer1@example.com")
|
|
self.student = User.objects.get(username="test-student1@example.com")
|
|
|
|
self.assignment = Assignment.objects.get(
|
|
slug="test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice"
|
|
)
|
|
self.assignment_subtasks = self.assignment.filter_user_subtasks()
|
|
self.assignment_task_ids = [t.id for t in self.assignment.tasks]
|
|
|
|
# self.client.force_login(self.trainer)
|
|
|
|
def test_student_can_upsertAssignmentCompletion(self):
|
|
self.client.force_login(self.student)
|
|
user_text_input = find_first(
|
|
self.assignment_subtasks, pred=lambda x: x["type"] == "user_text_input"
|
|
)
|
|
|
|
task_id = self.assignment_task_ids[0]
|
|
|
|
# Create file
|
|
uploaded_file = SimpleUploadedFile("file.txt", b"file_content")
|
|
file = UploadFile(
|
|
original_file_name="file.txt",
|
|
file_name="file.txt",
|
|
file_type="text/plain",
|
|
uploaded_by=self.student,
|
|
file=uploaded_file,
|
|
)
|
|
file.full_clean()
|
|
file.save()
|
|
|
|
file_id = str(file.id)
|
|
file_url = file.url
|
|
|
|
completion_data_string = json.dumps(
|
|
{
|
|
user_text_input["id"]: {"user_data": {"text": "Hallo via API"}},
|
|
task_id: {"user_data": {"fileId": file_id}},
|
|
}
|
|
).replace('"', '\\"')
|
|
|
|
query = f"""
|
|
mutation {{
|
|
upsert_assignment_completion(
|
|
assignment_id: {self.assignment.id}
|
|
course_session_id: {self.course_session.id}
|
|
completion_status: IN_PROGRESS
|
|
completion_data_string: "{completion_data_string}"
|
|
) {{
|
|
assignment_completion {{
|
|
id
|
|
completion_status
|
|
completion_data
|
|
task_completion_data
|
|
assignment_user {{ id }}
|
|
assignment {{ id }}
|
|
}}
|
|
}}
|
|
}}
|
|
"""
|
|
|
|
response = self.query(query)
|
|
self.assertResponseNoErrors(response)
|
|
|
|
data = json.loads(response.content)["data"]["upsert_assignment_completion"][
|
|
"assignment_completion"
|
|
]
|
|
|
|
self.assertEqual(data["assignment_user"]["id"], str(self.student.id))
|
|
self.assertEqual(data["assignment"]["id"], str(self.assignment.id))
|
|
self.assertEqual(data["completion_status"], "IN_PROGRESS")
|
|
self.assertDictEqual(
|
|
data["completion_data"],
|
|
{
|
|
user_text_input["id"]: {"user_data": {"text": "Hallo via API"}},
|
|
task_id: {"user_data": {"fileId": file_id}},
|
|
},
|
|
)
|
|
|
|
task_data = data["task_completion_data"][task_id]
|
|
self.maxDiff = None
|
|
self.assertEqual(task_data["user_data"]["fileId"], file_id)
|
|
self.assertEqual(task_data["user_data"]["fileInfo"]["id"], file_id)
|
|
self.assertEqual(task_data["user_data"]["fileInfo"]["name"], "file.txt")
|
|
self.assertTrue(
|
|
task_data["user_data"]["fileInfo"]["url"].startswith(
|
|
"https://s3.eu-central-1.amazonaws.com/myvbv-dev.iterativ.ch"
|
|
)
|
|
)
|
|
|
|
# check DB data
|
|
db_entry = AssignmentCompletion.objects.get(
|
|
assignment_user=self.student,
|
|
course_session_id=self.course_session.id,
|
|
assignment_id=self.assignment.id,
|
|
)
|
|
self.assertEqual(db_entry.completion_status, "IN_PROGRESS")
|
|
self.assertDictEqual(
|
|
db_entry.completion_data,
|
|
{
|
|
user_text_input["id"]: {"user_data": {"text": "Hallo via API"}},
|
|
task_id: {"user_data": {"fileId": file_id}},
|
|
},
|
|
)
|
|
|
|
# submit the response
|
|
completion_data_string = json.dumps(
|
|
{
|
|
user_text_input["id"]: {"user_data": {"text": "Hallo via API 2"}},
|
|
}
|
|
).replace('"', '\\"')
|
|
|
|
query = f"""
|
|
mutation {{
|
|
upsert_assignment_completion(
|
|
assignment_id: {self.assignment.id}
|
|
course_session_id: {self.course_session.id}
|
|
completion_status: SUBMITTED
|
|
completion_data_string: "{completion_data_string}"
|
|
) {{
|
|
assignment_completion {{
|
|
id
|
|
completion_status
|
|
completion_data
|
|
assignment_user {{ id }}
|
|
assignment {{ id }}
|
|
}}
|
|
}}
|
|
}}
|
|
"""
|
|
|
|
response = self.query(query)
|
|
self.assertResponseNoErrors(response)
|
|
|
|
data = json.loads(response.content)["data"]["upsert_assignment_completion"][
|
|
"assignment_completion"
|
|
]
|
|
|
|
self.assertEqual(data["assignment_user"]["id"], str(self.student.id))
|
|
self.assertEqual(data["assignment"]["id"], str(self.assignment.id))
|
|
self.assertEqual(data["completion_status"], "SUBMITTED")
|
|
self.assertDictEqual(
|
|
data["completion_data"],
|
|
{
|
|
user_text_input["id"]: {"user_data": {"text": "Hallo via API 2"}},
|
|
task_id: {"user_data": {"fileId": file_id}},
|
|
},
|
|
)
|
|
|
|
# check DB data
|
|
db_entry = AssignmentCompletion.objects.get(
|
|
assignment_user=self.student,
|
|
course_session_id=self.course_session.id,
|
|
assignment_id=self.assignment.id,
|
|
)
|
|
self.assertEqual(db_entry.completion_status, "SUBMITTED")
|
|
self.assertEqual(db_entry.submitted_at.date(), date.today())
|
|
self.assertDictEqual(
|
|
db_entry.completion_data,
|
|
{
|
|
user_text_input["id"]: {"user_data": {"text": "Hallo via API 2"}},
|
|
task_id: {"user_data": {"fileId": file_id}},
|
|
},
|
|
)
|
|
|
|
# check notification
|
|
self.assertEqual(Notification.objects.count(), 1)
|
|
notification = Notification.objects.first()
|
|
self.assertEqual(
|
|
"Test Student1 hat die geleitete Fallarbeit «Überprüfen einer Motorfahrzeugs-Versicherungspolice» abgegeben.",
|
|
notification.verb,
|
|
)
|
|
self.assertEqual(
|
|
"test-trainer1@example.com",
|
|
notification.recipient.email,
|
|
)
|
|
self.assertEqual(
|
|
"test-student1@example.com",
|
|
notification.actor.email,
|
|
)
|
|
self.assertEqual(
|
|
"USER_INTERACTION",
|
|
notification.notification_category,
|
|
)
|
|
self.assertEqual(
|
|
"CASEWORK_SUBMITTED",
|
|
notification.notification_trigger,
|
|
)
|
|
self.assertEqual(
|
|
notification.action_object,
|
|
db_entry,
|
|
)
|
|
self.assertEqual(
|
|
notification.course_session,
|
|
self.course_session,
|
|
)
|
|
self.assertTrue(
|
|
f"/course/test-lehrgang/cockpit/assignment" in notification.target_url
|
|
)
|
|
|
|
# second submit will fail
|
|
completion_data_string = json.dumps(
|
|
{
|
|
user_text_input["id"]: {"user_data": {"text": "Hallo via API 3"}},
|
|
}
|
|
).replace('"', '\\"')
|
|
|
|
query = f"""
|
|
mutation {{
|
|
upsert_assignment_completion(
|
|
assignment_id: {self.assignment.id}
|
|
course_session_id: {self.course_session.id}
|
|
completion_status: SUBMITTED
|
|
completion_data_string: "{completion_data_string}"
|
|
) {{
|
|
assignment_completion {{
|
|
id
|
|
completion_status
|
|
completion_data
|
|
assignment_user {{ id }}
|
|
assignment {{ id }}
|
|
}}
|
|
}}
|
|
}}
|
|
"""
|
|
|
|
response = self.query(query)
|
|
self.assertResponseHasErrors(response)
|
|
self.assertTrue("Cannot update completion status" in str(response.json()))
|
|
|
|
def test_expert_can_gradeAssignmentCompletion(self):
|
|
# setup AssignmentCompletion
|
|
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.student,
|
|
assignment=self.assignment,
|
|
learning_content_page=self.assignment.find_attached_learning_content(),
|
|
course_session=self.course_session,
|
|
completion_status="SUBMITTED",
|
|
submitted_at=timezone.now(),
|
|
completion_data={
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Ich würde nichts weiteres empfehlen."}
|
|
},
|
|
},
|
|
)
|
|
|
|
self.client.force_login(self.trainer)
|
|
|
|
completion_data_string = json.dumps(
|
|
{
|
|
user_text_input["id"]: {
|
|
"expert_data": {"points": 1, "comment": "Gut gemacht!"}
|
|
},
|
|
}
|
|
).replace('"', '\\"')
|
|
|
|
query = f"""
|
|
mutation {{
|
|
upsert_assignment_completion(
|
|
assignment_id: {self.assignment.id}
|
|
assignment_user_id: "{self.student.id}"
|
|
course_session_id: {self.course_session.id}
|
|
completion_status: EVALUATION_IN_PROGRESS
|
|
completion_data_string: "{completion_data_string}"
|
|
) {{
|
|
assignment_completion {{
|
|
id
|
|
completion_status
|
|
completion_data
|
|
assignment_user {{ id }}
|
|
assignment {{ id }}
|
|
}}
|
|
}}
|
|
}}
|
|
"""
|
|
|
|
print(query)
|
|
response = self.query(query)
|
|
self.assertResponseNoErrors(response)
|
|
|
|
data = json.loads(response.content)["data"]["upsert_assignment_completion"][
|
|
"assignment_completion"
|
|
]
|
|
|
|
self.assertEqual(data["assignment_user"]["id"], str(self.student.id))
|
|
self.assertEqual(data["assignment"]["id"], str(self.assignment.id))
|
|
self.assertEqual(data["completion_status"], "EVALUATION_IN_PROGRESS")
|
|
self.assertDictEqual(
|
|
data["completion_data"],
|
|
{
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Ich würde nichts weiteres empfehlen."},
|
|
"expert_data": {"points": 1, "comment": "Gut gemacht!"},
|
|
},
|
|
},
|
|
)
|
|
|
|
db_entry = AssignmentCompletion.objects.get(
|
|
assignment_user=self.student,
|
|
course_session_id=self.course_session.id,
|
|
assignment_id=self.assignment.id,
|
|
)
|
|
self.assertEqual(db_entry.completion_status, "EVALUATION_IN_PROGRESS")
|
|
self.assertDictEqual(
|
|
db_entry.completion_data,
|
|
{
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Ich würde nichts weiteres empfehlen."},
|
|
"expert_data": {"points": 1, "comment": "Gut gemacht!"},
|
|
},
|
|
},
|
|
)
|
|
|
|
# finish grading
|
|
completion_data_string = json.dumps(
|
|
{
|
|
user_text_input["id"]: {
|
|
"expert_data": {"points": 1, "comment": "Gut gemacht!"}
|
|
},
|
|
}
|
|
).replace('"', '\\"')
|
|
|
|
query = f"""
|
|
mutation {{
|
|
upsert_assignment_completion(
|
|
assignment_id: {self.assignment.id}
|
|
assignment_user_id: "{self.student.id}"
|
|
course_session_id: {self.course_session.id}
|
|
completion_status: EVALUATION_SUBMITTED
|
|
completion_data_string: "{completion_data_string}"
|
|
evaluation_points: 16,
|
|
) {{
|
|
assignment_completion {{
|
|
id
|
|
completion_status
|
|
completion_data
|
|
assignment_user {{ id }}
|
|
assignment {{ id }}
|
|
}}
|
|
}}
|
|
}}
|
|
"""
|
|
|
|
response = self.query(query)
|
|
self.assertResponseNoErrors(response)
|
|
|
|
data = json.loads(response.content)["data"]["upsert_assignment_completion"][
|
|
"assignment_completion"
|
|
]
|
|
|
|
self.assertEqual(data["assignment_user"]["id"], str(self.student.id))
|
|
self.assertEqual(data["assignment"]["id"], str(self.assignment.id))
|
|
self.assertEqual(data["completion_status"], "EVALUATION_SUBMITTED")
|
|
self.assertDictEqual(
|
|
data["completion_data"],
|
|
{
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Ich würde nichts weiteres empfehlen."},
|
|
"expert_data": {"points": 1, "comment": "Gut gemacht!"},
|
|
},
|
|
},
|
|
)
|
|
|
|
db_entry = AssignmentCompletion.objects.get(
|
|
assignment_user=self.student,
|
|
course_session_id=self.course_session.id,
|
|
assignment_id=self.assignment.id,
|
|
)
|
|
self.assertEqual(db_entry.completion_status, "EVALUATION_SUBMITTED")
|
|
self.assertEqual(db_entry.evaluation_points, 16)
|
|
self.assertEqual(db_entry.evaluation_max_points, 24)
|
|
self.assertTrue(db_entry.evaluation_passed)
|
|
self.assertDictEqual(
|
|
db_entry.completion_data,
|
|
{
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Ich würde nichts weiteres empfehlen."},
|
|
"expert_data": {"points": 1, "comment": "Gut gemacht!"},
|
|
},
|
|
},
|
|
)
|
|
|
|
# check notification
|
|
self.assertEqual(Notification.objects.count(), 1)
|
|
notification = Notification.objects.first()
|
|
self.assertEqual(
|
|
"Test Trainer1 hat die geleitete Fallarbeit «Überprüfen einer Motorfahrzeugs-Versicherungspolice» bewertet.",
|
|
notification.verb,
|
|
)
|
|
self.assertEqual(
|
|
"test-student1@example.com",
|
|
notification.recipient.email,
|
|
)
|
|
self.assertEqual(
|
|
"test-trainer1@example.com",
|
|
notification.actor.email,
|
|
)
|
|
self.assertEqual(
|
|
"USER_INTERACTION",
|
|
notification.notification_category,
|
|
)
|
|
self.assertEqual(
|
|
"CASEWORK_EVALUATED",
|
|
notification.notification_trigger,
|
|
)
|
|
self.assertEqual(
|
|
notification.action_object,
|
|
db_entry,
|
|
)
|
|
self.assertEqual(
|
|
notification.course_session,
|
|
self.course_session,
|
|
)
|
|
self.assertEqual(
|
|
notification.target_url,
|
|
"/course/test-lehrgang/learn/fahrzeug/überprüfen-einer-motorfahrzeug-versicherungspolice",
|
|
)
|
|
|
|
# `EVALUATION_SUBMITTED` will create a new AssignmentCompletionAuditLog
|
|
acl = AssignmentCompletionAuditLog.objects.get(
|
|
assignment_user=self.student,
|
|
course_session_id=self.course_session.id,
|
|
assignment_id=self.assignment.id,
|
|
completion_status="EVALUATION_SUBMITTED",
|
|
)
|
|
self.maxDiff = None
|
|
self.assertDictEqual(
|
|
acl.completion_data,
|
|
{
|
|
user_text_input["id"]: {
|
|
"id": user_text_input["id"],
|
|
"type": "user_text_input",
|
|
"value": {
|
|
"text": "Gibt es zusätzliche Deckungen, die du der Person empfehlen würdest? Begründe deine Empfehlung",
|
|
},
|
|
"user_data": {"text": "Ich würde nichts weiteres empfehlen."},
|
|
"expert_data": {"points": 1, "comment": "Gut gemacht!"},
|
|
},
|
|
},
|
|
)
|
|
self.assertEqual(acl.evaluation_points, 16)
|
|
self.assertEqual(acl.evaluation_max_points, 24)
|
|
self.assertTrue(acl.evaluation_passed)
|
|
|
|
def test_student_can_upsert_reflection(self):
|
|
"""
|
|
when upserting a reflection, it will store also the page_id of the learning content
|
|
"""
|
|
reflection = Assignment.objects.get(slug="test-lehrgang-assignment-reflexion")
|
|
reflection_subtasks = reflection.filter_user_subtasks()
|
|
reflection_learning_content = reflection.find_attached_learning_content()
|
|
|
|
self.client.force_login(self.student)
|
|
user_text_input = find_first(
|
|
reflection_subtasks, pred=lambda x: x["type"] == "user_text_input"
|
|
)
|
|
|
|
completion_data_string = json.dumps(
|
|
{
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Hallo via Reflection API"}
|
|
},
|
|
}
|
|
).replace('"', '\\"')
|
|
|
|
query = f"""
|
|
mutation {{
|
|
upsert_assignment_completion(
|
|
assignment_id: {reflection.id}
|
|
course_session_id: {self.course_session.id}
|
|
learning_content_page_id: {reflection_learning_content.id}
|
|
completion_status: IN_PROGRESS
|
|
completion_data_string: "{completion_data_string}"
|
|
) {{
|
|
assignment_completion {{
|
|
id
|
|
completion_status
|
|
completion_data
|
|
assignment_user {{ id }}
|
|
assignment {{ id }}
|
|
learning_content_page_id
|
|
}}
|
|
}}
|
|
}}
|
|
"""
|
|
|
|
response = self.query(query)
|
|
self.assertResponseNoErrors(response)
|
|
|
|
data = json.loads(response.content)["data"]["upsert_assignment_completion"][
|
|
"assignment_completion"
|
|
]
|
|
print(data)
|
|
self.assertEqual(data["assignment_user"]["id"], str(self.student.id))
|
|
self.assertEqual(data["assignment"]["id"], str(reflection.id))
|
|
self.assertEqual(data["completion_status"], "IN_PROGRESS")
|
|
self.assertEqual(
|
|
data["learning_content_page_id"], str(reflection_learning_content.id)
|
|
)
|
|
self.assertDictEqual(
|
|
data["completion_data"],
|
|
{
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Hallo via Reflection API"}
|
|
},
|
|
},
|
|
)
|
|
|
|
# check DB data
|
|
db_entry = AssignmentCompletion.objects.get(
|
|
assignment_user=self.student,
|
|
course_session_id=self.course_session.id,
|
|
assignment_id=reflection.id,
|
|
learning_content_page_id=reflection_learning_content.id,
|
|
)
|
|
self.assertEqual(db_entry.completion_status, "IN_PROGRESS")
|
|
self.assertDictEqual(
|
|
db_entry.completion_data,
|
|
{
|
|
user_text_input["id"]: {
|
|
"user_data": {"text": "Hallo via Reflection API"}
|
|
},
|
|
},
|
|
)
|