Merged in feature/VBV-339-assignment-cypress-test (pull request #79)
Feature/VBV-339 assignment cypress test UNFINISHED * Create assignment submission test data for cypress test * Add first assignment trainer test * Add first cypress test which checks DB entry with all instrumentation
This commit is contained in:
parent
b313bad031
commit
e130d65f37
|
|
@ -92,7 +92,7 @@ const assignmentCompletion = computed(() => assignmentStore.assignmentCompletion
|
|||
<div class="h-content flex">
|
||||
<div class="h-full w-1/2 overflow-y-auto bg-white">
|
||||
<!-- Left part content goes here -->
|
||||
<div class="p-10">
|
||||
<div class="p-10" data-cy="student-submission">
|
||||
<h3>Ergebnisse</h3>
|
||||
<div class="my-6 flex items-center">
|
||||
<img
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ async function startEvaluation() {
|
|||
</p>
|
||||
|
||||
<div>
|
||||
<button class="btn-primary" @click="startEvaluation()">
|
||||
<button class="btn-primary" data-cy="start-evaluation" @click="startEvaluation()">
|
||||
<span
|
||||
v-if="
|
||||
props.assignmentCompletion.completion_status === 'evaluation_in_progress'
|
||||
|
|
@ -74,7 +74,9 @@ async function startEvaluation() {
|
|||
Bewertung fortsetzen
|
||||
</span>
|
||||
<span
|
||||
v-if="props.assignmentCompletion.completion_status === 'evaluation_submitted'"
|
||||
v-else-if="
|
||||
props.assignmentCompletion.completion_status === 'evaluation_submitted'
|
||||
"
|
||||
>
|
||||
Bewertung ansehen
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ const evaluateAssignmentCompletionDebounced = useDebounceFn(
|
|||
|
||||
<template>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div>
|
||||
<div data-cy="evaluation-task">
|
||||
<div class="text-bold mb-4 text-sm">
|
||||
Beurteilungskriterium {{ taskIndex + 1 }} /
|
||||
{{ props.assignment.evaluation_tasks.length }}
|
||||
|
|
@ -91,6 +91,7 @@ const evaluateAssignmentCompletionDebounced = useDebounceFn(
|
|||
v-for="(subTask, index) in task.value.sub_tasks"
|
||||
:key="index"
|
||||
class="mb-4 flex items-center last:mb-0"
|
||||
:data-cy="`subtask-${subTask.points}`"
|
||||
>
|
||||
<input
|
||||
:id="String(index)"
|
||||
|
|
@ -120,6 +121,7 @@ const evaluateAssignmentCompletionDebounced = useDebounceFn(
|
|||
label="Begründung"
|
||||
:disabled="!props.allowEdit"
|
||||
placeholder="Hier muss zwingend eine Begründung erfasst werden."
|
||||
data-cy="reason-text"
|
||||
@update:model-value="onUpdateText($event)"
|
||||
></ItTextarea>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ const assignmentDetail = computed(() =>
|
|||
:key="csu.user_id + csu.session_title"
|
||||
:name="`${csu.first_name} ${csu.last_name}`"
|
||||
:avatar-url="csu.avatar_url"
|
||||
:data-cy="csu.last_name"
|
||||
>
|
||||
<template #center>
|
||||
<section class="flex w-full justify-between px-8">
|
||||
|
|
@ -130,6 +131,7 @@ const assignmentDetail = computed(() =>
|
|||
v-if="submissionStatusForUser(csu.user_id)?.progressStatus === 'success'"
|
||||
:to="`/course/${props.courseSession.course.slug}/cockpit/assignment/${assignment.assignmentId}/${csu.user_id}`"
|
||||
class="w-full text-right underline"
|
||||
data-cy="show-results"
|
||||
>
|
||||
Ergebnisse anzeigen
|
||||
</router-link>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ module.exports = defineConfig({
|
|||
viewportWidth: 1280,
|
||||
viewportHeight: 720,
|
||||
retries: {
|
||||
runMode: 1,
|
||||
runMode: 2,
|
||||
openMode: 0,
|
||||
},
|
||||
reporter: "junit",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
// ids for cypress test data
|
||||
export const ADMIN_USER_ID = -1;
|
||||
export const TEST_TRAINER1_USER_ID = -11;
|
||||
export const TEST_STUDENT1_USER_ID = -21;
|
||||
export const TEST_STUDENT2_USER_ID = -22;
|
||||
|
||||
export const TEST_COURSE_SESSION_BERN_ID = -1;
|
||||
export const TEST_COURSE_SESSION_ZURICH_ID = -2;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { login } from "./helpers";
|
||||
import { login } from "../helpers";
|
||||
|
||||
describe("student test", () => {
|
||||
beforeEach(() => {
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
import { TEST_STUDENT1_USER_ID } from "../../consts";
|
||||
import { login } from "../helpers";
|
||||
|
||||
describe("trainer test", () => {
|
||||
beforeEach(() => {
|
||||
cy.manageCommand("cypress_reset --create-completion");
|
||||
login("test-trainer1@example.com", "test");
|
||||
});
|
||||
|
||||
it("can open cockpit assignment page and open user assignment", () => {
|
||||
cy.visit("/course/test-lehrgang/cockpit/assignment");
|
||||
|
||||
cy.get('[data-cy="Student1"]').should("contain", "Ergebnisse abgegeben");
|
||||
cy.get('[data-cy="Student1"]').find('[data-cy="show-results"]').click();
|
||||
|
||||
cy.get('[data-cy="student-submission"]').should("contain", "Ergebnisse");
|
||||
cy.get('[data-cy="student-submission"]').should("contain", "Student1");
|
||||
});
|
||||
|
||||
it("can start evaluation and store evaluation results", () => {
|
||||
cy.visit("/course/test-lehrgang/cockpit/assignment");
|
||||
|
||||
cy.get('[data-cy="Student1"]').find('[data-cy="show-results"]').click();
|
||||
|
||||
cy.get('[data-cy="start-evaluation"]').click();
|
||||
cy.get('[data-cy="evaluation-task"]').should(
|
||||
"contain",
|
||||
"Beurteilungskriterium 1 / 5"
|
||||
);
|
||||
|
||||
// without text input the button should be disabled
|
||||
cy.get('[data-cy="next-step"]').should("be.disabled");
|
||||
|
||||
// with text you can continue
|
||||
cy.get('[data-cy="subtask-4"]').click();
|
||||
cy.get('[data-cy="reason-text"]').type("Gut gemacht!");
|
||||
// wait for debounce
|
||||
cy.wait(500);
|
||||
cy.get('[data-cy="next-step"]').click();
|
||||
|
||||
cy.get('[data-cy="evaluation-task"]').should(
|
||||
"contain",
|
||||
"Beurteilungskriterium 2 / 5"
|
||||
);
|
||||
cy.get('[data-cy="subtask-2"]').click();
|
||||
cy.get('[data-cy="reason-text"]').type("Nicht so gut");
|
||||
cy.wait(500);
|
||||
|
||||
// revisit step 1 will show stored data
|
||||
cy.get('[data-cy="previous-step"]').click();
|
||||
cy.get('[data-cy="reason-text"]')
|
||||
.find("textarea")
|
||||
.should("have.value", "Gut gemacht!");
|
||||
|
||||
// even after reload
|
||||
cy.reload();
|
||||
cy.get('[data-cy="reason-text"]')
|
||||
.find("textarea")
|
||||
.should("have.value", "Gut gemacht!");
|
||||
|
||||
// it can access step directly via url
|
||||
cy.url().then((url) => {
|
||||
const step2Url = url.replace("step=1", "step=2");
|
||||
console.log(step2Url);
|
||||
cy.visit(step2Url);
|
||||
});
|
||||
|
||||
cy.get('[data-cy="reason-text"]')
|
||||
.find("textarea")
|
||||
.should("have.value", "Nicht so gut");
|
||||
|
||||
// load AssignmentCompletion from DB and check
|
||||
cy.loadAssignmentCompletion(
|
||||
"assignment_user_id",
|
||||
TEST_STUDENT1_USER_ID
|
||||
).then((ac) => {
|
||||
expect(ac.completion_status).to.equal("evaluation_in_progress");
|
||||
expect(JSON.stringify(ac.completion_data)).to.include("Nicht so gut");
|
||||
expect(Cypress._.values(ac.completion_data)).to.deep.include({
|
||||
expert_data: { points: 2, text: "Nicht so gut" },
|
||||
});
|
||||
expect(Cypress._.values(ac.completion_data)).to.deep.include({
|
||||
expert_data: { points: 4, text: "Gut gemacht!" },
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -52,55 +52,77 @@
|
|||
|
||||
const _ = Cypress._;
|
||||
|
||||
Cypress.Commands.add('manageCommand', (command, preCommand = '') => {
|
||||
Cypress.Commands.add("manageCommand", (command, preCommand = "") => {
|
||||
const execCommand = `${preCommand} python server/manage.py ${command} --settings=config.settings.test_cypress`;
|
||||
console.log(execCommand);
|
||||
return cy.exec(execCommand, { failOnNonZeroExit: false }).then(result => {
|
||||
if(result.code) {
|
||||
throw new Error(`Execution of "${command}" failed
|
||||
return cy
|
||||
.exec(
|
||||
// hack to add my asdf python instance to the path
|
||||
// so I can run the test directly from within IntelliJ
|
||||
`PATH=/Users/daniel/workspace/vbv_lernwelt/.direnv/python-3.10.6/bin:$PATH && ${execCommand}`,
|
||||
{
|
||||
failOnNonZeroExit: false,
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
if (result.code) {
|
||||
throw new Error(`Execution of "${command}" failed
|
||||
Exit code: ${result.code}
|
||||
Stdout:\n${result.stdout}
|
||||
Stderr:\n${result.stderr}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('manageShellCommand', (command) => {
|
||||
Cypress.Commands.add("manageShellCommand", (command) => {
|
||||
return cy.manageCommand(`shell -c '${command}'`);
|
||||
});
|
||||
|
||||
function loadObjectJson(key, value, djangoModelPath, serializerModelPath) {
|
||||
const djangoModel = _.last(djangoModelPath.split('.'));
|
||||
const djangoModelImportPath = _.initial(djangoModelPath.split('.')).join('.');
|
||||
const serializerModel = _.last(serializerModelPath.split('.'));
|
||||
const serializerModelImportPath = _.initial(serializerModelPath.split('.')).join('.');
|
||||
const djangoModel = _.last(djangoModelPath.split("."));
|
||||
const djangoModelImportPath = _.initial(djangoModelPath.split(".")).join(".");
|
||||
const serializerModel = _.last(serializerModelPath.split("."));
|
||||
const serializerModelImportPath = _.initial(
|
||||
serializerModelPath.split(".")
|
||||
).join(".");
|
||||
|
||||
let filterPart = `${key}=${value}`;
|
||||
if(_.isArray(key)) {
|
||||
filterPart = _.zip(key, value).map(([k, v]) => {
|
||||
return `${k}=${v}`;
|
||||
}).join(',');
|
||||
if (_.isArray(key)) {
|
||||
filterPart = _.zip(key, value)
|
||||
.map(([k, v]) => {
|
||||
return `${k}=${v}`;
|
||||
})
|
||||
.join(",");
|
||||
}
|
||||
|
||||
const command = `from ${djangoModelImportPath} import ${djangoModel};
|
||||
from ${serializerModelImportPath} import ${serializerModel};
|
||||
from myservice.apps.core.serializers import create_json_from_objects;
|
||||
object = ${djangoModel}.objects.filter(${filterPart}).first();
|
||||
print(create_json_from_objects(object, ${serializerModel}, many=False));
|
||||
exit()`.replace(/(?:\r\n|\r|\n)/g, '');
|
||||
return cy.manageShellCommand(command).then(result => {
|
||||
from ${serializerModelImportPath} import ${serializerModel};
|
||||
from vbv_lernwelt.core.serializers import create_json_from_objects;
|
||||
object = ${djangoModel}.objects.filter(${filterPart}).first();
|
||||
print(create_json_from_objects(object, ${serializerModel}, many=False));
|
||||
exit();
|
||||
`.replace(/(?:\r\n|\r|\n)/g, "");
|
||||
return cy.manageShellCommand(command).then((result) => {
|
||||
const objectJson = JSON.parse(result.stdout);
|
||||
console.log(objectJson);
|
||||
return objectJson;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
Cypress.Commands.add('makeSelfEvaluation', (answers) => {
|
||||
Cypress.Commands.add("loadAssignmentCompletion", (key, value) => {
|
||||
return loadObjectJson(
|
||||
key,
|
||||
value,
|
||||
"vbv_lernwelt.assignment.models.AssignmentCompletion",
|
||||
"vbv_lernwelt.assignment.serializers.AssignmentCompletionSerializer"
|
||||
);
|
||||
});
|
||||
|
||||
Cypress.Commands.add("makeSelfEvaluation", (answers) => {
|
||||
for (let i = 0; i < answers.length; i++) {
|
||||
const answer = answers[i];
|
||||
if (answer) {
|
||||
cy.get('[data-cy="success"]').click();
|
||||
cy.get('[data-cy="success"]').click();
|
||||
} else {
|
||||
cy.get('[data-cy="fail"]').click();
|
||||
}
|
||||
|
|
@ -112,7 +134,6 @@ Cypress.Commands.add('makeSelfEvaluation', (answers) => {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
// Cypress.Commands.add('loadApiClientRequestResponseLog', (key, value) => {
|
||||
// return loadObjectJson(
|
||||
// key,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ from django.conf.urls.static import static
|
|||
from django.contrib import admin
|
||||
from django.contrib.auth.decorators import user_passes_test
|
||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||
from django.urls import include, path, re_path
|
||||
from django.urls import include, path, re_path, register_converter
|
||||
from django.urls.converters import IntConverter
|
||||
from django.views import defaults as default_views
|
||||
from grapple import urls as grapple_urls
|
||||
from ratelimit.exceptions import Ratelimited
|
||||
|
|
@ -50,6 +51,20 @@ from wagtail.admin import urls as wagtailadmin_urls
|
|||
from wagtail.documents import urls as wagtaildocs_urls
|
||||
|
||||
|
||||
class SignedIntConverter(IntConverter):
|
||||
regex = r"-?\d+"
|
||||
|
||||
def to_python(self, value):
|
||||
return int(value)
|
||||
|
||||
def to_url(self, value):
|
||||
return str(value)
|
||||
|
||||
|
||||
# Register the converter
|
||||
register_converter(SignedIntConverter, "signed_int")
|
||||
|
||||
|
||||
def raise_example_error(request):
|
||||
"""
|
||||
raise error to check if it gets logged
|
||||
|
|
@ -88,15 +103,17 @@ urlpatterns = [
|
|||
|
||||
# course
|
||||
path(r"api/course/sessions/", get_course_sessions, name="get_course_sessions"),
|
||||
path(r"api/course/sessions/<course_session_id>/users/", get_course_session_users,
|
||||
path(r"api/course/sessions/<signed_int:course_session_id>/users/",
|
||||
get_course_session_users,
|
||||
name="get_course_session_users"),
|
||||
path(r"api/course/page/<slug_or_id>/", course_page_api_view,
|
||||
name="course_page_api_view"),
|
||||
path(r"api/course/completion/mark/", mark_course_completion_view,
|
||||
name="mark_course_completion"),
|
||||
path(r"api/course/completion/<course_session_id>/", request_course_completion,
|
||||
path(r"api/course/completion/<signed_int:course_session_id>/",
|
||||
request_course_completion,
|
||||
name="request_course_completion"),
|
||||
path(r"api/course/completion/<course_session_id>/<int:user_id>/",
|
||||
path(r"api/course/completion/<signed_int:course_session_id>/<signed_int:user_id>/",
|
||||
request_course_completion_for_user,
|
||||
name="request_course_completion_for_user"),
|
||||
|
||||
|
|
@ -105,15 +122,17 @@ urlpatterns = [
|
|||
name="upsert_user_assignment_completion"),
|
||||
path(r"api/assignment/evaluate/", evaluate_assignment_completion,
|
||||
name="evaluate_assignment_completion"),
|
||||
path(r"api/assignment/<int:assignment_id>/<int:course_session_id>/",
|
||||
path(r"api/assignment/<signed_int:assignment_id>/<signed_int:course_session_id>/",
|
||||
request_assignment_completion,
|
||||
name="request_assignment_completion"),
|
||||
path(r"api/assignment/<int:assignment_id>/<int:course_session_id>/status/",
|
||||
request_assignment_completion_status,
|
||||
name="request_assignment_completion_status"),
|
||||
path(r"api/assignment/<int:assignment_id>/<int:course_session_id>/<int:user_id>/",
|
||||
request_assignment_completion_for_user,
|
||||
name="request_assignment_completion_for_user"),
|
||||
path(
|
||||
r"api/assignment/<signed_int:assignment_id>/<signed_int:course_session_id>/status/",
|
||||
request_assignment_completion_status,
|
||||
name="request_assignment_completion_status"),
|
||||
path(
|
||||
r"api/assignment/<signed_int:assignment_id>/<signed_int:course_session_id>/<signed_int:user_id>/",
|
||||
request_assignment_completion_for_user,
|
||||
name="request_assignment_completion_for_user"),
|
||||
|
||||
# documents
|
||||
path(r'api/core/document/start/', document_upload_start,
|
||||
|
|
|
|||
|
|
@ -3,3 +3,12 @@ DEFAULT_RICH_TEXT_FEATURES = [
|
|||
"bold",
|
||||
"italic",
|
||||
]
|
||||
|
||||
# ids for cypress test data
|
||||
ADMIN_USER_ID = -1
|
||||
TEST_TRAINER1_USER_ID = -11
|
||||
TEST_STUDENT1_USER_ID = -21
|
||||
TEST_STUDENT2_USER_ID = -22
|
||||
|
||||
TEST_COURSE_SESSION_BERN_ID = -1
|
||||
TEST_COURSE_SESSION_ZURICH_ID = -2
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
from django.contrib.auth.hashers import make_password
|
||||
from django.contrib.auth.models import Group
|
||||
|
||||
from vbv_lernwelt.core.constants import (
|
||||
ADMIN_USER_ID,
|
||||
TEST_STUDENT1_USER_ID,
|
||||
TEST_STUDENT2_USER_ID,
|
||||
TEST_TRAINER1_USER_ID,
|
||||
)
|
||||
from vbv_lernwelt.core.models import User
|
||||
|
||||
default_users = [
|
||||
|
|
@ -70,12 +76,14 @@ def create_default_users(user_model=User, group_model=Group, default_password=No
|
|||
avatar_url="",
|
||||
password=default_password,
|
||||
language="de",
|
||||
id=None,
|
||||
):
|
||||
student_user, created = _get_or_create_user(
|
||||
user_model=user_model,
|
||||
username=email,
|
||||
password=password,
|
||||
language=language,
|
||||
id=id,
|
||||
)
|
||||
student_user.first_name = first_name
|
||||
student_user.last_name = last_name
|
||||
|
|
@ -83,9 +91,9 @@ def create_default_users(user_model=User, group_model=Group, default_password=No
|
|||
student_user.groups.add(student_group)
|
||||
student_user.save()
|
||||
|
||||
def _create_admin_user(email, first_name, last_name, avatar_url=""):
|
||||
def _create_admin_user(email, first_name, last_name, avatar_url="", id=None):
|
||||
admin_user, created = _get_or_create_user(
|
||||
user_model=user_model, username=email, password=default_password
|
||||
user_model=user_model, username=email, password=default_password, id=id
|
||||
)
|
||||
admin_user.is_superuser = True
|
||||
admin_user.is_staff = True
|
||||
|
|
@ -107,6 +115,7 @@ def create_default_users(user_model=User, group_model=Group, default_password=No
|
|||
first_name="Peter",
|
||||
last_name="Adminson",
|
||||
avatar_url="/static/avatars/avatar_iterativ.png",
|
||||
id=ADMIN_USER_ID,
|
||||
)
|
||||
|
||||
for user_data in default_users:
|
||||
|
|
@ -232,19 +241,25 @@ def create_default_users(user_model=User, group_model=Group, default_password=No
|
|||
|
||||
# users for cypress tests
|
||||
_create_student_user(
|
||||
id=TEST_TRAINER1_USER_ID,
|
||||
email="test-trainer1@example.com",
|
||||
first_name="Test",
|
||||
last_name="Trainer1",
|
||||
avatar_url="/static/avatars/uk1.patrizia.huggel.jpg",
|
||||
)
|
||||
_create_student_user(
|
||||
id=TEST_STUDENT1_USER_ID,
|
||||
email="test-student1@example.com",
|
||||
first_name="Test",
|
||||
last_name="Student1",
|
||||
avatar_url="/static/avatars/uk1.michael.meier.jpg",
|
||||
)
|
||||
_create_student_user(
|
||||
id=TEST_STUDENT2_USER_ID,
|
||||
email="test-student2@example.com",
|
||||
first_name="Test",
|
||||
last_name="Student2",
|
||||
avatar_url="/static/avatars/uk1.lina.egger.jpg",
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -252,6 +267,7 @@ def _get_or_create_user(user_model, *args, **kwargs):
|
|||
username = kwargs.get("username", None)
|
||||
password = kwargs.get("password", None)
|
||||
language = kwargs.get("language", "de")
|
||||
id = kwargs.get("id", None)
|
||||
created = False
|
||||
|
||||
user = user_model.objects.filter(username=username).first()
|
||||
|
|
@ -262,6 +278,7 @@ def _get_or_create_user(user_model, *args, **kwargs):
|
|||
password=make_password(password),
|
||||
email=username,
|
||||
language=language,
|
||||
id=id,
|
||||
)
|
||||
created = True
|
||||
return user, created
|
||||
|
|
|
|||
|
|
@ -1,15 +1,37 @@
|
|||
import djclick as click
|
||||
|
||||
from vbv_lernwelt.assignment.models import AssignmentCompletion
|
||||
from vbv_lernwelt.assignment.models import Assignment, AssignmentCompletion
|
||||
from vbv_lernwelt.core.constants import (
|
||||
TEST_COURSE_SESSION_BERN_ID,
|
||||
TEST_STUDENT1_USER_ID,
|
||||
)
|
||||
from vbv_lernwelt.core.models import User
|
||||
from vbv_lernwelt.course.models import CourseCompletion
|
||||
from vbv_lernwelt.course.creators.test_course import (
|
||||
create_test_assignment_submitted_data,
|
||||
)
|
||||
from vbv_lernwelt.course.models import CourseCompletion, CourseSession
|
||||
from vbv_lernwelt.notify.models import Notification
|
||||
|
||||
|
||||
@click.command()
|
||||
def command():
|
||||
@click.option(
|
||||
"--create-completion/--no-create-completion",
|
||||
default=False,
|
||||
help="will create completion data for some users",
|
||||
)
|
||||
def command(create_completion):
|
||||
print("cypress reset data")
|
||||
CourseCompletion.objects.all().delete()
|
||||
Notification.objects.all().delete()
|
||||
AssignmentCompletion.objects.all().delete()
|
||||
User.objects.all().update(language="de")
|
||||
|
||||
if create_completion:
|
||||
print("create completion data for test course")
|
||||
create_test_assignment_submitted_data(
|
||||
assignment=Assignment.objects.get(
|
||||
slug="test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice"
|
||||
),
|
||||
course_session=CourseSession.objects.get(id=TEST_COURSE_SESSION_BERN_ID),
|
||||
user=User.objects.get(id=TEST_STUDENT1_USER_ID),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,15 @@
|
|||
from rest_framework import serializers
|
||||
from rest_framework.renderers import JSONRenderer
|
||||
|
||||
from vbv_lernwelt.core.models import User
|
||||
from vbv_lernwelt.course.models import CourseSessionUser
|
||||
|
||||
|
||||
def create_json_from_objects(objects, serializer_class, many=True) -> str:
|
||||
serializer = serializer_class(objects, many=many)
|
||||
return JSONRenderer().render(serializer.data).decode("utf-8")
|
||||
|
||||
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
course_session_experts = serializers.SerializerMethodField()
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,17 @@ from wagtail.models import Site
|
|||
|
||||
from vbv_lernwelt.assignment.creators.create_assignments import create_test_assignment
|
||||
from vbv_lernwelt.assignment.models import Assignment
|
||||
from vbv_lernwelt.assignment.services import update_assignment_completion
|
||||
from vbv_lernwelt.competence.factories import (
|
||||
CompetencePageFactory,
|
||||
CompetenceProfilePageFactory,
|
||||
PerformanceCriteriaFactory,
|
||||
)
|
||||
from vbv_lernwelt.competence.models import CompetencePage
|
||||
from vbv_lernwelt.core.constants import (
|
||||
TEST_COURSE_SESSION_BERN_ID,
|
||||
TEST_COURSE_SESSION_ZURICH_ID,
|
||||
)
|
||||
from vbv_lernwelt.core.models import User
|
||||
from vbv_lernwelt.core.tests.helpers import create_locales_for_wagtail
|
||||
from vbv_lernwelt.course.consts import COURSE_TEST_ID
|
||||
|
|
@ -65,11 +70,13 @@ def create_test_course(include_uk=True, include_vv=True, with_sessions=False):
|
|||
# course sessions
|
||||
cs_bern = CourseSession.objects.create(
|
||||
course_id=COURSE_TEST_ID,
|
||||
title="Bern 2022 a",
|
||||
title="Test Bern 2022 a",
|
||||
id=TEST_COURSE_SESSION_BERN_ID,
|
||||
)
|
||||
cs_zurich = CourseSession.objects.create(
|
||||
course_id=COURSE_TEST_ID,
|
||||
title="Zürich 2022 a",
|
||||
title="Test Zürich 2022 a",
|
||||
id=TEST_COURSE_SESSION_ZURICH_ID,
|
||||
)
|
||||
|
||||
trainer1 = User.objects.get(email="test-trainer1@example.com")
|
||||
|
|
@ -100,6 +107,30 @@ def create_test_course(include_uk=True, include_vv=True, with_sessions=False):
|
|||
return course
|
||||
|
||||
|
||||
def create_test_assignment_submitted_data(assignment, course_session, user):
|
||||
if assignment and course_session and user:
|
||||
subtasks = assignment.filter_user_subtasks(subtask_types=["user_text_input"])
|
||||
for index, subtask in enumerate(subtasks):
|
||||
user_text = f"Lorem ipsum dolor sit amet... {index}"
|
||||
|
||||
update_assignment_completion(
|
||||
assignment_user=user,
|
||||
assignment=assignment,
|
||||
course_session=course_session,
|
||||
completion_data={
|
||||
subtask["id"]: {
|
||||
"user_data": {"text": user_text},
|
||||
}
|
||||
},
|
||||
)
|
||||
update_assignment_completion(
|
||||
assignment_user=user,
|
||||
assignment=assignment,
|
||||
course_session=course_session,
|
||||
completion_status="submitted",
|
||||
)
|
||||
|
||||
|
||||
def create_test_course_with_categories(apps=None, schema_editor=None):
|
||||
if apps is not None:
|
||||
Course = apps.get_model("course", "Course")
|
||||
|
|
|
|||
Loading…
Reference in New Issue